public class Test {
public void say(String name) {
new RunnableWithReturn() {
@Override
public Object execute() {
System.out.println(name); // 編譯錯誤:name 必須是 final 或 effectively final
return null;
}
};
}
}
interface RunnableWithReturn {
Object execute();
}
Java 語言規範(JLS)規定:**匿名內部類(及局部類、Lambda)只能訪問 final 或 effectively final 的局部變量**。
方法參數 name 在方法體中可被修改(如 name = "other"),故非 effectively final,編譯報錯。
public void say(final String name) { ... }
public void say(String name) {
final String finalName = name; // 復制引用
new RunnableWithReturn() {
@Override
public Object execute() {
System.out.println(finalName); // 訪問 final 副本
return null;
}
};
}
public void say(String name) {
RunnableWithReturn r = () -> {
System.out.println(name); // name 不能在 Lambda 中被修改
return null;
};
}
Java 選擇值捕獲簡化內存模型,避免多線程下局部變量生命周期結束後內部類仍持有引用導致未定義行為。
var = ...、var++、for (var : ...) 等)。匿名內部類訪問外部局部變量,**必須保證變量不可變**。Java 7 用 final,Java 8+ 允許 effectively final(隱式 final)。最佳實踐:參數加 final 或 提取 final 副本,代碼意圖清晰,兼容所有版本。