Какие особенности есть у статической (static) переменной?

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

Ответ

В контексте написания автотестов на Java (например, для Selenium) я использую статические переменные с осторожностью, понимая их особенности:

  1. Принадлежность классу, а не объекту: Статическая переменная существует в единственном экземпляре для всего класса. Все объекты этого класса разделяют одну копию этой переменной. В тестах это удобно для хранения глобальной конфигурации (например, пути к драйверу) или общего счетчика.
  2. Инициализация при загрузке класса: Переменная инициализируется один раз при первом обращении к классу или создании его первого объекта. Это важно учитывать, чтобы не получить неожиданное состояние между независимыми тестовыми прогонами.
  3. Доступ без создания экземпляра: К статической переменной можно обращаться напрямую через имя класса ClassName.variableName. В тестовых фреймворках так часто объявляют драйвер или логгер.
  4. Общее состояние для всех экземпляров: Изменение статической переменной в одном объекте влияет на все другие объекты этого класса. Это может быть источником хрупких тестов, если тесты запускаются параллельно и используют общий ресурс.

Пример из тестового фреймворка:

public class TestBase {
    // Статический драйвер, чтобы быть доступным во всех тестовых классах
    protected static WebDriver driver;
    // Статический счетчик выполненных тестов (для отчета)
    public static int testsExecuted = 0;

    @BeforeAll
    public static void setUp() {
        // Инициализация драйвера происходит один раз для всех тестов в классе
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
    }

    @AfterEach
    public void tearDown() {
        testsExecuted++; // Изменяем общий для всех тестов счетчик
        // driver.quit(); // Нельзя закрывать здесь, если драйвер статический и общий!
    }
}

public class LoginTest extends TestBase {
    @Test
    public void testValidLogin() {
        // Использую статический драйвер из родительского класса
        driver.get("https://example.com/login");
        // ... логика теста
        System.out.println("Всего выполнено тестов: " + TestBase.testsExecuted);
    }
}

Важно: Для изоляции тестов и поддержки параллельного запуска предпочитаю использовать ThreadLocal для драйвера или инстансы Page Object, а не чистые статические переменные.