Lambdas 在初始化之前访问封闭 class 的最终字段

Lambdas accessing final fields of the enclosing class before initialisation

我发现在从封闭的 lambda 表达式访问 class 的最终字段时无法解释的行为。这是示例程序:

public class FinalAccessTest {

  // Some fields
  private int nonfinalfield=4;
  private final int directfinalfield=5;
  private final int constructorfinalfield;

  // element method for the final field with delayed assignment
  private int getConstructorFinalField() { return constructorfinalfield; }

  // Some lambda expressions accessing the fields from above
  private final Supplier<Integer> nonfinalsupp=()->nonfinalfield;  // OK
  private final Supplier<Integer> directfinalsupp=()->directfinalfield;  // OK
  private final Supplier<Integer> constructorfinalsuppA=
    ()->this.constructorfinalfield;  // OK
  private final Supplier<Integer> constructorfinalsuppB=
    ()->getConstructorFinalField();   // OK

  // This one does not compile: The blank final field
  //   constructorfinalfield may not have been initialized
  //private Supplier<Integer> constructorfinalsuppC=()->constructorfinalfield;

  public FinalAccessTest() {
    System.out.println(constructorfinalsuppA.get()); // prints "0"
    System.out.println(constructorfinalsuppB.get()); // prints "0"

    // Does not compile: "may not have been initialized"
    //System.out.println(constructorfinalfield);

    constructorfinalfield=6;
    System.out.println(constructorfinalsuppA.get()); // prints "6"
    System.out.println(constructorfinalsuppB.get()); // prints "6"
    System.out.println(constructorfinalfield); // Compiles and prints "6"

    // now access to a non-final field
    System.out.println(nonfinalsupp.get()); // prints "4"
    nonfinalfield=17;
    System.out.println(nonfinalsupp.get()); // prints "17"

  }

  public static void main(String[] args) { new FinalAccessTest(); }

}

显然可以访问 class 的最终字段,它在构造函数中初始化,然后在 lambda 表达式中由

实际初始化

另一方面,似乎通常无法通过简单地在 lambda 表达式中引用 <field> 来访问此类 final 字段。我想,lambda 中的 this 总是引用封闭的 class,因此 <field>this.<field> 实际上是相同的。

为了避免混淆,这一切仅适用于final 字段,这些字段在构造函数 中初始化。对于在声明中初始化的非最终字段或最终字段,完全可以通过 <field> 访问,并在 lambda 调用时使用字段的值。

这是怎么回事?这是 lambda 表达式 definition/engine 的普遍缺点、特定 Java 版本 (8u66) 中的错误还是只是一个功能?我有点不解。我哪里错了?

对象初始值设定项(即表单字段的声明 = class 中的值)运行 构造函数之前按出现顺序。因此,第一个声明的是当时已经初始化的所有访问字段,而在构造函数中创建的字段只会在 各自的对象初始化程序之后被初始化。

this.constructorFinalField 是 Eclipse Photon 中的一个错误。所以不一致。