Поведение поставщика Java 8: конечная переменная не может быть инициализирована
Java запрещает использование конечной переменной внутри поставщика, поскольку она не может быть инициализирована, но добавляет "(это)". переменная заставляет ее компилироваться и работать нормально.
Кроме того, вызов такого поставщика приводит к ошибке NullPointerException вместо ошибки компилятора, если он вызывается перед назначением переменной и выполняется как ожидается, если вызвано после.
Описанное здесь поведение?
Я использую OpenJDK 1.8.0_151.
Пример:
import java.util.function.Supplier;
class Example {
final String str;
Supplier<Integer> test1 = () -> str.length(); // DOES NOT COMPILE
Supplier<Integer> test2 = () -> this.str.length(); // DOES NOT COMPILE
Supplier<Integer> test3 = () -> (this.str).length(); // DOES NOT COMPILE
Supplier<Integer> test4 = () -> (this).str.length(); // OK
Example(String str) {
System.out.println(test4.get()); // NullPointerException
this.str = str;
System.out.println(test4.get()); // OK
}
}
---
javac Example.java
Example.java:7: error: variable str might not have been initialized
Supplier<Integer> test1 = () -> str.length(); // DOES NOT COMPILE
^
Example.java:8: error: variable str might not have been initialized
Supplier<Integer> test2 = () -> this.str.length(); // DOES NOT COMPILE
^
Example.java:9: error: variable str might not have been initialized
Supplier<Integer> test3 = () -> (this.str).length(); // DOES NOT COMPILE
^
3 errors
Ответы
Ответ 1
От JLS версия 9, глава 16:
Каждая локальная переменная (§14.4) и каждое пустое конечное поле (§4.12.4, §8.3.1.2) должен иметь определенно присвоенное значение, когда любой доступ к его значение имеет значение.
Доступ к его значению состоит из простого имени переменной (или для поля, простое имя поля, квалифицируемого этим) происходящее где угодно в выражении, кроме как левый операнд простой оператор присваивания = (§15.26.1).
str
- это простое имя конечного поля, а this.str
- простое имя поля, имеющего квалификацию this
. (this).str
не относится ни к одному из этих случаев ((this)
не считается "квалифицированным с помощью this
" ), поэтому он не считается доступом.