10

Java 不允许在供应商内部使用 final 变量,因为它可能没有被初始化,但在前面加上“(this)”。to 变量使它编译并运行良好。

此外,如果在分配变量之前调用此类供应商会导致 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
4

1 回答 1

6

JLS 版本 9,第 16 章开始:

每个局部变量(第 14.4 节)和每个空白最终字段(第 4.12.4 节、第 8.3.1.2 节)在对其值进行任何访问时都必须具有明确分配的值。

对其值的访问包括变量的简单名称(或者,对于一个字段,由 this 限定的字段的简单名称)出现在表达式中的任何位置,除了作为简单赋值运算符的左侧操作数 = (§ 15.26.1)。

str是最终字段的简单名称,并且this.str是由 . 限定的字段的简单名称this(this).str不属于这两种情况((this)不计为“合格this”),因此不计为访问。

于 2018-03-05T20:47:34.863 回答