Ili*_*dis 5 java java-record java-17
我有以下记录:
public record A(List<String> list) {
public A {
this.list = new ArrayList<>(list);
}
}
Run Code Online (Sandbox Code Playgroud)
但我得到这个编译错误:
无法为最终变量赋值
另一方面,这可以编译:
public record A(List<String> list) {
public A {
list = new ArrayList<>(list);
}
}
Run Code Online (Sandbox Code Playgroud)
为什么是这样?
Mar*_*eel 13
原因在JEP 395:记录中给出(强调我的):
可以使用与记录头匹配的形式参数列表显式声明规范构造函数,如上所示。还可以通过省略形式参数列表来更紧凑地声明它。在这样一个紧凑的规范构造函数中,参数是隐式声明的,记录组件对应的私有字段不能在主体中赋值,而是在构造函数末尾自动分配给相应的形参(this.x = x;)。紧凑的形式有助于开发人员专注于验证和规范化参数,而无需将参数分配给字段的繁琐工作。
换句话说,使用紧凑的规范构造函数,您可以更新构造函数参数,然后将该构造函数参数分配给编译器生成的代码中的字段。
这意味着声明
public record A(List<String> list) {
public A {
this.list = new ArrayList<>(list);
}
}
Run Code Online (Sandbox Code Playgroud)
本质上生成:
public record A(List<String> list) {
public A(List<String> list) {
this.list = new ArrayList<>(list);
this.list = list;
}
}
Run Code Online (Sandbox Code Playgroud)
它尝试两次分配该list字段。Final 字段不允许这样做。
另一方面,以下代码:
public record A(List<String> list) {
public A {
list = new ArrayList<>(list);
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
public record A(List<String> list) {
public A(List<String> list) {
list = new ArrayList<>(list);
this.list = list;
}
}
Run Code Online (Sandbox Code Playgroud)
这完全没问题,因为该list字段仅分配一次。