JavaRush /Курсы /JAVA 25 SELF /Модификаторы доступа

Модификаторы доступа

JAVA 25 SELF
15 уровень , 1 лекция
Открыта

1. Обзор модификаторов доступа

В Java есть четыре уровня доступа для классов, полей, методов и конструкторов:

Модификатор Где доступен?
public
Везде: внутри класса, в других классах, в других пакетах
protected
Внутри класса, в подклассах (наследниках), в других классах того же пакета
(package-private)
Только внутри пакета (если модификатор не указан явно)
private
Только внутри текущего класса

Давайте разберём каждый из них подробнее — с примерами, шутками и неожиданными поворотами.

public — публичный доступ

public — это как объявление на весь мир: «Всем вход разрешён!». Если класс, поле, метод или конструктор объявлен как public, к нему можно обратиться из любого другого класса, даже из другого пакета.

Пример:

public class Cat {
    public String name;
    public void sayMeow() {
        System.out.println("Мяу!");
    }
}

К этому классу и его полям/методам можно обратиться откуда угодно. Это удобно, если вы хотите, чтобы ваш класс был доступен всем: например, если вы пишете библиотеку.

Но! Публичные поля — это не всегда хорошо (см. прошлую лекцию). Обычно публичными делают только методы, которые должны быть доступны извне, а вот поля почти всегда оставляют private.

private — доступ только внутри класса

private — это как сейф с кодовым замком: никто, кроме самого класса, не может получить доступ к этим членам. Даже наследники (подклассы) не видят приватных полей и методов!

Пример:

public class Cat {
    private String secretName;

    public void setSecretName(String name) {
        secretName = name;
    }

    public String getSecretName() {
        return secretName;
    }
}

Здесь secretName нельзя прочитать или изменить напрямую из другого класса. Только сам Cat может это сделать (или его методы). Это основа инкапсуляции: мы скрываем внутренние детали и предоставляем к ним доступ только через методы.

protected — защищённый доступ

protected — это как VIP-пропуск: доступ разрешён классу, его наследникам (даже если они в других пакетах) и всем классам внутри текущего пакета.

Пример:

public class Animal {
    protected int age;

    protected void growOlder() {
        age++;
    }
}

Теперь любой класс, который наследует Animal, сможет обращаться к полю age и методу growOlder().

public class Cat extends Animal {
    public void haveBirthday() {
        growOlder();
        System.out.println("Коту исполнилось " + age + " лет!");
    }
}

Также к protected-членам имеют доступ все классы внутри того же пакета.

(package-private) — доступ внутри пакета

Если вы не указали модификатор доступа вообще, то член класса считается package-private (или «доступ по умолчанию»). Это как дверь без замка, но только для своих: доступ разрешён только классам из того же пакета.

Пример:

class Dog {
    String name; // package-private
    void bark() { // package-private
        System.out.println("Гав!");
    }
}

Класс Dog, его поле name и метод bark() доступны только внутри того же пакета. Попытка обратиться к ним из другого пакета вызовет ошибку компиляции.

2. Применение модификаторов к полям и методам

Почему поля почти всегда делают private

Поля класса — это его внутреннее состояние. Если их оставить публичными, любой внешний код сможет их менять в любой момент. Это как если бы вы позволили незнакомым детям играть с вашей мебелью, как с Lego: однажды вы проснётесь, а холодильник стоит в ванной вверх дном.

Пример плохой инкапсуляции:

public class Person {
    public String name;
    public int age;
}

Пример хорошей инкапсуляции:

public class Person {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Методы (геттеры и сеттеры) позволяют контролировать, как именно внешние классы могут изменять поля. Например, можно запретить отрицательный возраст.

Когда методы делают public, protected или package-private

  • public — если метод должен быть доступен всем. Обычно это основная функциональность класса.
  • protected — если метод нужен только наследникам или внутри пакета (например, вспомогательные методы, которые могут быть полезны в дочерних классах).
  • package-private — если метод нужен только внутри пакета, но не должен быть доступен снаружи (например, внутренние детали реализации).
  • private — если метод используется только внутри самого класса (например, вспомогательные методы для внутренней логики).

Пример:

public class BankAccount {
    private double balance;

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    protected void applyInterest() {
        balance *= 1.05;
    }

    void internalAudit() {
        // package-private: только для классов внутри пакета
    }

    private void logAction(String action) {
        // только для внутренних нужд класса
    }
}

3. Примеры кода: класс с разными уровнями доступа

Давайте создадим класс, в котором есть всё: публичные, приватные, защищённые и пакетные члены. Заодно попробуем обратиться к ним из других классов и посмотрим, что получится.

package zoo;

public class Animal {
    public String publicName = "Доступно всем";
    protected String protectedName = "Только для наследников и пакета";
    String packageName = "Только для пакета";
    private String privateName = "Только для Animal";

    public void publicMethod() {
        System.out.println("Публичный метод");
    }

    protected void protectedMethod() {
        System.out.println("Защищённый метод");
    }

    void packageMethod() {
        System.out.println("Пакетный метод");
    }

    private void privateMethod() {
        System.out.println("Приватный метод");
    }
}

Теперь попробуем обратиться к этим членам из другого класса в том же пакете:

package zoo;

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName);   // OK
        System.out.println(animal.packageName);     // OK
        System.out.println(animal.privateName);  // Ошибка: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                   // OK
        animal.packageMethod();                     // OK
        animal.privateMethod();                  // Ошибка: private
    }
}

А теперь попробуем обратиться к этим членам из другого пакета:

package other;

import zoo.Animal;

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName); // Ошибка: protected
        System.out.println(animal.packageName);   // Ошибка: package-private
        System.out.println(animal.privateName);   // Ошибка: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                // Ошибка: protected
        animal.packageMethod();                  // Ошибка: package-private
        animal.privateMethod();                  // Ошибка: private
    }
}

Вывод:

  • public — доступен везде.
  • protected — доступен внутри пакета и в наследниках (даже из других пакетов, если через наследование).
  • package-private — только внутри пакета.
  • private — только внутри класса.

4. Best practices: как выбирать модификатор доступа

Минимизируйте область видимости

Чем меньше кода может видеть ваше поле или метод, тем лучше. Открывайте только то, что действительно нужно внешнему коду. Это называется принципом минимальной видимости (principle of least privilege).

  • Поля почти всегда должны быть private. Исключения — только для настоящих констант (public static final), но об этом подробнее в следующих лекциях.
  • Методы делают public только если они часть внешнего интерфейса класса.
  • Вспомогательные методы (внутренняя логика) — private.
  • Методы для наследниковprotected.
  • Внутренние сервисные методы для пакетаpackage-private.

Почему это важно?

  • Любое изменение в деталях реализации может сломать чужой код, если детали раскрыты.
  • Класс становится сложнее тестировать и поддерживать.
  • Случайные ошибки (например, неправильное изменение поля) могут привести к багам.

Иногда новички думают: «Зачем мне эти сложности, пусть всё будет public!» Но потом, когда проект разрастается, приходится переписывать половину программы только потому, что кто-то напрямую менял поля класса.

5. Типичные ошибки при работе с модификаторами доступа

Ошибка № 1: Оставили поля public или package-private по умолчанию.
Если не указать модификатор, поле или метод будет доступен для всех классов внутри пакета. Это может привести к неожиданным ситуациям, если кто-то начнёт напрямую менять ваши поля.

Ошибка № 2: Попытка обратиться к private-члену из другого класса.
Компилятор не даст этого сделать — получите ошибку. Но если вы вдруг решите обойти это через reflection (отражение) — добро пожаловать в мир багов и неожиданных падений.

Ошибка № 3: Слишком много public.
Если всё подряд объявлять public, то класс становится похож на открытую коробку с проводами — любой может дёрнуть не за тот провод и всё сломать.

Ошибка № 4: Не используете protected для методов, которые нужны только наследникам.
Если метод нужен только для расширения в дочерних классах, объявите его protected, а не public.

Ошибка № 5: Неявная package-private видимость.
Иногда забывают указать модификатор, и метод становится доступен всему пакету. Это может быть неожиданностью, если вы думали, что он private.

1
Задача
JAVA 25 SELF, 15 уровень, 1 лекция
Недоступна
Читаем имя на цифровой визитке 🃏
Читаем имя на цифровой визитке 🃏
1
Задача
JAVA 25 SELF, 15 уровень, 1 лекция
Недоступна
Волшебный калькулятор с секретным механизмом ➕
Волшебный калькулятор с секретным механизмом ➕
1
Задача
JAVA 25 SELF, 15 уровень, 1 лекция
Недоступна
Внутренняя помощь в команде разработки 🤝
Внутренняя помощь в команде разработки 🤝
1
Задача
JAVA 25 SELF, 15 уровень, 1 лекция
Недоступна
Управление цифровой библиотекой: кто что может делать 🏛️
Управление цифровой библиотекой: кто что может делать 🏛️
Комментарии (3)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Grrbrr7 Уровень 21
29 ноября 2025
Как запустить дебаг текущей задачи? А то дебагер идёт по всему проекту javarush и валится в задачах которые давно пройдены
Anonymous #3630645 Уровень 19
25 декабря 2025
Я просто удаляю предыдущие задачи
Ksanders Уровень 32
5 ноября 2025
В четвертой задаче в условии задачи уже содержится ответ