Должны ли все поля класса быть приватными (private) для соблюдения инкапсуляции?

«Должны ли все поля класса быть приватными (private) для соблюдения инкапсуляции?» — вопрос из категории ООП, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Не обязательно все. Инкапсуляция — это о сокрытии внутреннего состояния и деталей реализации, а не о тотальном объявлении всех полей private.

Руководство по выбору модификатора доступа для полей:

Модификатор Когда использовать Пример
private По умолчанию для инкапсуляции. Поле — часть внутреннего состояния, не предназначено для прямого внешнего доступа. private double balance; (баланс счета)
protected Когда поле должно быть доступно классам-наследникам в рамках иерархии, но скрыто от внешнего мира. protected String databaseUrl; (в абстрактном DAO)
Без модификатора (package-private) Для доступа внутри одного пакета, часто используется для тестирования или взаимодействия тесно связанных классов. Logger log; (вспомогательное поле для классов пакета)
public Крайне редко, в основном для констант. Поле является публичной, неизменяемой частью API. public static final String DEFAULT_CURRENCY = "USD";

Практическое правило:

  1. Начинайте с private.
  2. Ослабляйте доступ только при явной необходимости и с пониманием последствий для связности кода.
  3. Для предоставления контролируемого доступа к полю используйте геттеры/сеттеры (которые могут содержать валидацию или логику).
public class Employee {
    // Private — внутреннее состояние
    private String name;
    private double salary;

    // Protected — для наследников (например, разных типов сотрудников)
    protected int accessLevel;

    // Package-private — для внутренней утилиты в том же пакете
    String internalId;

    // Public — только для истинных констант
    public static final String COMPANY_NAME = "TechCorp";

    // Контролируемый доступ через методы
    public String getName() { return name; }
    public void setSalary(double salary) {
        if (salary >= 0) this.salary = salary; // Валидация
    }
}