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 表明该对象在所有意图和目的上都已“初始化”?很好奇为什么这会有所不同。
我已经进行了一些搜索,但没有找到任何能够很好地阐明这一点的内容。
提前致谢!
最佳答案
Does a call to a member method constitute a "freeze action" or is it indicative to the JVM that the object is, for all intents and purposes, "initialized"? Curious why this makes a difference.
问题是你的类是从上到下初始化的。这意味着您的静态字段尚未初始化,即您的 map 为 null
。
另一种方法是添加一个静态初始化 block ,以便在所有内容初始化后调用。
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
字段,但您应该避免这样做,除非没有其他选择。
关于java - 从实例初始值设定项更新静态最终字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49785724/