[英]Updating a static final field from an instance initializer
Java禁止从初始化程序访问最终的静态字段。 例如:
public enum Example {
ValueA("valueAA", "valueAB"),
ValueB("valueBA", "valueBB");
final static Map<String, Example> exampleByPropertyA = new HashMap<>();
final String propertyA;
final String propertyB;
Example(String propertyA, String propertyB) {
this.propertyA = propertyA;
this.propertyB = propertyB;
Example.exampleByPropertyA.put(propertyA, this); // <- Not permitted
}
}
但是,如果静态Map
的更新是在初始化程序调用的单独方法中执行的,那么这很好。 例如:
public enum Example {
ValueA("valueAA", "valueAB"),
ValueB("valueBA", "valueBB");
final static Map<String, Example> exampleByPropertyA = new HashMap<>();
final String propertyA;
final String propertyB;
Example(String propertyA, String propertyB) {
this.propertyA = propertyA;
this.propertyB = propertyB;
addExample(this);
}
private addExample(Example example) {
Example.exampleByPropertyA.put(example.propertyA, example); // <- Permitted
}
}
鉴于此上下文,我的问题是:对成员方法的调用是否构成“冻结操作”,还是指向JVM,对于所有意图和目的,该对象是“初始化的”? 好奇为什么这会产生影响。
我已经做了一些搜索,但没有找到任何能够清楚地表达出来的东西。
先感谢您!
对成员方法的调用是否构成“冻结操作”,或者它是否指示JVM对于所有意图和目的,“初始化”对象是什么? 好奇为什么这会产生影响。
问题是你的课程是从上到下初始化的。 这意味着您的静态字段尚未初始化,即您的Map为null
。
另一种方法是添加一个静态初始化块,以便在所有内容初始化后调用。
static {
for (Example e: values()) {
addExample(e);
}
}
private static addExample(Example example) {
Example prev = exampleByPropertyA.put(example.propertyA, example);
assert prev == null;
}
注意:您可以在初始化之前查看最终变量。 这意味着即使不使用反射, final
也可以具有前后值。
public class A {
final String text = getText();
private String getText() {
System.out.println("text= " + text);
return "is set";
}
public static void main(String... args) {
new A().getText();
}
}
版画
text= null
text= is set
使用反射即使在初始化之后也可以改变final
字段,但除非没有其他选项,否则应该避免这样做。
执行您要执行的操作的正确方法是编写静态初始化程序,该程序在创建所有枚举之后运行。
防御性编程:您还应该添加一个简单的检查以防止编程错误。
public enum Example {
ValueA("valueAA", "valueAB"),
ValueB("valueBA", "valueBB");
final static Map<String, Example> exampleByPropertyA = new HashMap<>();
static {
for (Example ex : values())
if (exampleByPropertyA.put(ex.propertyA, ex) != null)
throw new IllegalStateException("Duplicate propertyA: " + ex.propertyA);
}
final String propertyA;
final String propertyB;
Example(String propertyA, String propertyB) {
this.propertyA = propertyA;
this.propertyB = propertyB;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.