Поведение поставщика 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"), так что это не считается доступом.

Другие вопросы по тегам