Есть ли ограничения на публичность у геттеров в Java?

«Есть ли ограничения на публичность у геттеров в Java?» — вопрос из категории Java, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

С точки зрения тестирования (QA) это важно по двум причинам:

  1. Доступ к состоянию для проверок. Часто в модульных или интеграционных тестах нам нужно проверить внутреннее состояние объекта после выполнения операции. Если геттер private, тест в другом классе не сможет к нему обратиться. В таких случаях я либо:

    • Договариваюсь с командой о необходимости package-private или protected геттера для тестов, если это не нарушает инкапсуляцию для production-кода.
    • Использую рефлексию (например, библиотеку JUnit с @VisibleForTesting или PowerMock) для доступа к приватным полям/методам только в крайних случаях, так как это усложняет тесты.
  2. Тестирование самого геттера. Если геттер содержит какую-либо логику (валидацию, преобразование данных), его нужно протестировать как любой публичный метод.

Пример из практики тестирования:

// Production-класс
public class UserSession {
    private String sessionToken;
    private long expiryTime;

    // Публичный геттер для использования в других частях приложения
    public String getSessionToken() {
        return sessionToken;
    }

    // Геттер с package-private доступом. Нужен для тестов в том же пакете,
    // чтобы проверить корректность расчета времени истечения сессии.
    long getExpiryTime() {
        return expiryTime;
    }
}

// Test-класс (в том же пакете)
package com.example.auth;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class UserSessionTest {
    @Test
    void sessionExpiryIsSetCorrectly() {
        UserSession session = new UserSession("token123");
        // Мы можем проверить внутреннюю логику, потому что геттер доступен в пакете
        assertTrue(session.getExpiryTime() > System.currentTimeMillis());
    }
}