Объявление локальных переменных как final без инициализатора и назначение в if-statement
Я просто сделал небольшое изменение кода, чтобы отключить предупреждение FindBugs, которое потребовало переноса некоторого кода в анонимный внутренний класс. Чтобы получить доступ к некоторым переменным, я должен был объявить их как final
. Итак, это фрагмент кода после изменения:
final File[] libPath; // libPath is final but assignment takes place later
if (libraryPath != null) {
libPath = pathToFiles(libraryPath);
} else {
libPath = new File[0];
}
Этот компилируется с использованием языка, установленного на Java 6 в текущем Eclipse (версия 3.7.1). Однако я уверен, что это использовало, чтобы дать ошибку в некоторой предыдущей версии. Кажется, компилятор принимает эту конструкцию, когда она может определить, что будет.
Мой вопрос: является ли это законным в Java 6 или это то, что теперь работает из-за побочного эффекта поддержки Java 7, добавленного в eclipse 3.7.1? Мы наблюдали такие побочные эффекты при определенном использовании дженериков, которые работают в 3.7.1, но не компилировались в 3.7.0.
Ответы
Ответ 1
Это было разрешено и отлично работало с Java 1.1, и вы не столкнетесь с проблемами с другими компиляторами или IDE.
Это стандартное поведение в Java и впервые было официально определено в Спецификация Java Language Specification 2nd Edition.
Ответ 2
Это нормально. он называется пустой конечной
цитата из вики:
Конечная переменная может быть инициализирована только один раз, либо через инициализатор или оператор присваивания. Его не нужно инициализировать на точка объявления: это называется "пустой конечной" переменной. пустая переменная конечного экземпляра класса должна быть определенно назначена в конце каждого конструктора класса, в котором он объявлен; аналогично, пустая конечная статическая переменная должна быть определенно назначена в статическом инициализаторе класса, в котором он объявлен: в противном случае в обоих случаях возникает ошибка времени компиляции. [4] (Примечание: если переменная является ссылкой, это означает, что переменная не может быть переопределить ссылку на другой объект. Но объект, который он ссылки по-прежнему изменяемы, если он был первоначально изменен.)
Пустое окончательное
Пустое окончание, введенное в Java 1.1, является конечной переменной в декларации которого отсутствует инициализатор. [5] [6] Только пустой финал может назначается один раз и при назначении не должен быть назначен. В Чтобы сделать это, компилятор Java выполняет анализ потока, чтобы гарантировать, для каждого присваивания пустой конечной переменной переменная определенно неназначенный перед назначением; в противном случае время компиляции ошибка возникает. [7]
В общем, компилятор Java гарантирует, что пустой финал не будет используется до тех пор, пока не будет присвоено значение, и после присвоения значения теперь конечная переменная не может быть переназначена другим значением. [8]
ссылка: http://en.wikipedia.org/wiki/Final_%28Java%29
Ответ 3
Спецификация языка Java содержит целую главу, посвященную этому поведению (Глава 16
Определенное задание).
Это поведение полностью определено, поэтому я думаю, что вы неправильно истолковали что-то, когда говорите, что использовали для создания ошибки в предыдущих версиях.
Ответ 4
Это хорошо. Переменная не имеет значения и назначается только один раз. Он не сработает, если вы сначала присвоили ему значение null
.
Ответ 5
Я бы настоятельно рекомендовал вместо этого использовать этот код:
final File[] libPath = ibraryPath == null ? new File[0] : pathToFiles(libraryPath);
Это не зависит от какой-либо версии компилятора, но на 100% поддерживается Java с понятным значением.
Ответ 6
Да, это будет работать и безопасно использовать во всех версиях java, которые я видел (1.3 +).
final означает, что вы не можете изменить значение объекта после его инициализации, если вы поместили нуль при объявлении, который он сломал.