[英]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.