Поведение поставщика 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 ответ
Каждая локальная переменная (§14.4) и каждое пустое конечное поле (§4.12.4, §8.3.1.2) должны иметь определенно назначенное значение, когда происходит любой доступ к ее значению.
Доступ к его значению состоит из простого имени переменной (или, для поля, простого имени поля, определяемого этим), встречающегося в любом месте выражения, кроме как в качестве левого операнда оператора простого присваивания = (§15.26.1).
str
это простое имя конечного поля, и this.str
простое имя поля, определяемое как this
, (this).str
не подпадает ни под один из этих случаев ((this)
не считается "квалифицированным this
"), так что это не считается доступом.