Какие модификаторы доступа существуют в Java и в чем их отличие?

«Какие модификаторы доступа существуют в Java и в чем их отличие?» — вопрос из категории Java Core, который задают на 24% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Java четыре модификатора доступа, которые контролируют видимость классов, методов и полей. Их применение основано на принципе инкапсуляции.

Сравнительная таблица

Модификатор Уровень класса Уровень пакета Подклассы (наследники) Остальной мир (другие пакеты)
private Да Нет Нет Нет
default (package-private) Да Да Нет* Нет
protected Да Да Да Нет
public Да Да Да Да

*Подкласс, находящийся в другом пакете, не имеет доступа к default-членам родительского класса.

Примеры и использование

package com.example;

public class AccessExample {
    private String secret = "Доступ только внутри AccessExample"; // Полная инкапсуляция

    String packagePrivate = "Доступ в пакете com.example"; // Default (без модификатора)

    protected void inheritMe() { // Доступ в пакете и подклассах
        System.out.println("Метод для наследников");
    }

    public static final String API_CONSTANT = "PUBLIC"; // Открытый API
}

// В другом пакете
package com.other;
import com.example.AccessExample;

class SubClass extends AccessExample {
    void test() {
        // System.out.println(secret); // Ошибка: private
        // System.out.println(packagePrivate); // Ошибка: default (другой пакет)
        inheritMe(); // OK: protected (наследник)
        System.out.println(AccessExample.API_CONSTANT); // OK: public
    }
}

Практические рекомендации

  1. private — основной инструмент для сокрытия внутренней реализации. Делайте поля приватными, предоставляя доступ через геттеры/сеттеры.
  2. default — используйте осознанно для связи внутри модуля или пакета, когда функциональность не является частью публичного API.
  3. protected — применяйте в классах, предназначенных для наследования, чтобы предоставить наследникам доступ к внутренним вспомогательным методам.
  4. public — минимально необходимый набор для API класса. Избегайте публичных полей (кроме констант static final).

Правило: Давайте минимально необходимый уровень доступа. Начинайте с private и расширяйте его только при явной необходимости.