gpt4 book ai didi

javac - 为什么 Java lambda 在实例字段初始化方面与嵌套类的处理方式不同?

转载 作者:行者123 更新时间:2023-12-02 01:21:38 28 4
gpt4 key购买 nike

在 javac 1.8.0_77 中这个类不编译:

    import java.util.function.*;
public class xx {
final Object obj;

final Supplier<Object> supplier1 = new Supplier<Object>() {
@Override
public Object get() {
return xx.this.obj;
}
};

final Supplier<Object> supplier2 = () -> { return this.obj; };

xx(Object obj) {
this.obj = obj;
}
}

这是错误:

    xx.java:12: error: variable obj might not have been initialized
final Supplier<Object> supplier2 = () -> { return this.obj; };
^
1 error

问题:

  1. 根据 JLS,此错误的生成是否正确?
  2. 如果是这样,JLS 处理 @FunctionalInterface 背后的原因是什么?在这方面,lamba 实现 ( supplier2) 与其等效的内部类实现 (supplier1) 有何不同?

编辑添加 (2022/9/21)

仅供引用,这是一个修复此问题的简单编译器补丁。在 Flow.AssignAnalyzer 中,它导致 lambda 在字段初始化方面被视为非构造函数方法(即忽略它们) :

diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index 20abb281211..7e77d594143 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -2820,30 +2909,33 @@ public class Flow {
@Override
public void visitLambda(JCLambda tree) {
final Bits prevUninits = new Bits(uninits);
final Bits prevInits = new Bits(inits);
int returnadrPrev = returnadr;
+ int firstadrPrev = firstadr;
int nextadrPrev = nextadr;
ListBuffer<PendingExit> prevPending = pendingExits;
try {
returnadr = nextadr;
+ firstadr = nextadr;
pendingExits = new ListBuffer<>();
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
JCVariableDecl def = l.head;
scan(def);
inits.incl(def.sym.adr);
uninits.excl(def.sym.adr);
}
if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
scanExpr(tree.body);
} else {
scan(tree.body);
}
}
finally {
returnadr = returnadrPrev;
uninits.assign(prevUninits);
inits.assign(prevInits);
pendingExits = prevPending;
+ firstadr = firstadrPrev;
nextadr = nextadrPrev;
}
}

最佳答案

浏览 JSR 335 中的 JLS 更改,这对我来说似乎是一个遗漏:

事实上,第 16 章中唯一的变化是(使用粗体字进行添加):

Throughout the rest of this chapter, we will, unless explicitly stated otherwise, write V to represent an in-scope (6.3) local variable or a blank final field (for rules of definite assignment) or a blank final variable (for rules of definite unassignment).

归根结底,编译器在 lambda 情况下不提示似乎是正确的,但为了保持一致性,JLS 也应该被修改以涵盖这种情况。

编辑::OpenJDK 已经有一个 spec bug为此,在我们发言时正在提议更改。

关于javac - 为什么 Java lambda 在实例字段初始化方面与嵌套类的处理方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39881295/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com