Ошибка “variable might not have been initialized”

312
23 августа 2017, 16:19

Возник вопрос по логике кода. Почему компилятор не пропускает такой код?

String testStr;
if (check > 0) {
  testStr = "abc";
}
System.out.println(testStr != null ? testStr: "0");

При компиляции выдаётся ошибка:

Error:(134, 32) java: ... variable testStr might not have been initialized

Хотя вроде как логичным будет просто вывести "0" в случае, если testStr не было инициализировано... Какая тут логика?

Answer 1

В Java локальные переменные не имеют значения по умолчанию. Это означает что при простом объявлении переменной у неё не будет значения. В приведённом коде при check<=0 переменная так и останется не инициализированной при обращении к ней, на что и ругается компилятор.

String testStr=null;

Это решит проблему

Answer 2

Есть два варианта интерпретации данного кода:

  1. Программист хотел объявить переменную с каким-то значением, но допустил ошибку в коде: пропустил присвоение значения либо блок else. В этом случае компилятор поможет ему найти ошибку.
  2. Программист полагает, что testStr будет инициализировано как null по умолчанию. В этом случае компилятор заставит программиста инициализировать переменную как null явно.

Разработчики Java пришли к выводу, что:

  • важно отловить возможные ошибки;
  • неудобства, связанные с инициализацией локальных переменных, незначительны.

Обязательная инициализация локальных переменных определена в спецификации Java:

Chapter 16. Definite Assignment

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

An access to its value consists of the simple name of the variable (or, for a field, the simple name of the field qualified by this) occurring anywhere in an expression except as the left-hand operand of the simple assignment operator = (§15.26.1).

For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.

Перевод (из книги «Язык программирования Java SE 8. Подробное описание»)

Глава 16. Определенное присваивание

Каждая локальная переменная (§14.4) и каждое пустое final-поле (§4.12.4, §8.3.1.2) должны иметь определенно присвоенное значение при любом обращении к их значениям.

Обращение к их значениям состоит из простого имени переменной (или, в случае поля, простого имени поля, квалифицированного ключевым словом this), находящегося в любом месте выражения, за исключением левого операнда оператора присваивания = (§15.26.1).

Для каждого обращения к локальной переменной или к пустому final-полю x, x должно быть определенно присвоено до этого обращения, иначе генерируется ошибка времени компиляции.

Посмотрите также обсуждения этого вопроса в английской версии:

  • Why are local variables not initialized in Java?
  • Why must local variables, including primitives, always be initialized in Java?
READ ALSO
Импорт метода/класса из jar файла

Импорт метода/класса из jar файла

Создал testjar файл проекта

341
Работа с websocket в Spring

Работа с websocket в Spring

Здравствуйте, мой вопрос заключается в следующем: у меня есть чат, реализованный с помощью javaxwebsocket, мне захотелось переделать его на Spring,...

437
Как дождаться нажатия на кнопку в Swing?

Как дождаться нажатия на кнопку в Swing?

У меня в классе RegistrationFrame, который реализует интерфейс ActionListener, по нажатию на кнопку создается класс PersonВ отдельном классе, Test, в отдельном...

301
Google map APIv2 работает на Android 5.1, но не работает на 6.0.1

Google map APIv2 работает на Android 5.1, но не работает на 6.0.1

Столкнулся с этой проблемой при компиляции программы на реальном устройстве 60

338