Вопрос с собеседования · Java

Библиотека объявляет public static final String VERSION = "1.0". В новой версии значение изменили на "2.0" и заменили только jar библиотеки. Что увидит уже скомпилированное приложение?

SeniorОсновы языка
Коротко

Старое "1.0": static final примитив или строка с константным инициализатором — константа времени компиляции, её значение вписано прямо в байт-код потребителя. Без перекомпиляции приложения новое значение не подхватится.

  • Ссылки на класс библиотеки в байт-коде вообще не остаётся
  • Обход: инициализировать через метод — VERSION = String.valueOf("2.0") или читать из ресурса
  • Касается и switch по константам

А ещё Публичные константы в API — часть бинарного контракта

Подробно

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

Что хотят услышать

  • Механизм подстановки констант.
  • Последствия для библиотек и обход.

Частые ошибки

  • Считать, что подмена jar обновит все значения.
  • Забывать, что обращение к константе не инициализирует класс.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Новое значение "2.0", как и для любого другого статического поля
  • ✗Будет брошено NoSuchFieldError при обращении
  • ✓Старое "1.0": константа вкомпилирована в класс потребителя
  • ✗Значение будет зависеть от того, какой класс загрузчик успел загрузить первым

Что спросят дальше

  • Как объявить поле так, чтобы оно не стало константой времени компиляции?
  • Почему обращение к константе не инициализирует класс?

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования