enum Case {CASE_ONE,CASE_TWO,CASE_THREE;private static final int counter;private int valueDependsOnCounter;static {int sum = 0;for(int i = 0; i<10; i++) {sum +=i;}counter = sum;} Case() {this.valueDependsOnCounter = counter*counter;}}
您認為編譯和運行代碼的結果是什么?
- 編譯器錯誤
- 運行時錯誤
- 運行正常,但valueDependsOnCounter具有奇怪的值
- 沒關系
稍加思考。 (擾流塊)答案是按以下順序的第8個字母:bdcadcbabcad。
為了闡明這一點,有必要檢查以下內容:
A.類中靜態初始化的順序:
- 靜態viaribales出現的順序
- 靜態塊出現的順序
- 實例變量的出現順序
- 構造函數
B.構造函數調用的順序(這也適用于靜態變量):
- 超級班
- 本地班
C.用Java表示枚舉對象的方式:
1)名稱E的枚舉除其他外具有一個隱式靜態最終字段,該枚舉對每個枚舉成員都具有類型E的n。 更具體地說,Caseclass可以通過以下方式編寫:
enum Case {public static final Case CASE_ONE;public static final Case CASE_TWO;public static final Case CASE_THREE;…}
2)上面的成員按照聲明的順序出現,并且位于枚舉的所有其他靜態成員之上(這意味著它們是第一個要初始化的成員)。
3)枚舉常量被認為是在相應字段初始化時創建的。
因此,編譯器會發出類似“從枚舉或實例初始化程序訪問靜態成員計數器是非法的”之類的錯誤。 這是因為枚舉被初始化的順序:
1)公共靜態最終案例CASE_ONE;
2)公共靜態最終案例CASE_TWO; 3)公共靜態最終案例CASE_THREE; 4)公共靜態最終計數器; 5)
static {..counter = something;}
6)
Case() {this.valueDependsOnCounter = counter*counter;}
需要做的第一件事是初始化CASE_ONE,但是必須調用Case()構造函數,該構造函數又取決于僅在靜態{}塊中初始化(但尚未執行)的計數器。 。 現在,從構造函數訪問靜態變量將是一個巨大的限制,但這正是這種流程所暗示的,即您不能在枚舉的構造函數中使用靜態變量。 幸運的是,這不太正確。 該錯誤實際上試圖告訴我們的是:“從構造函數,實例初始值設定項塊或實例變量初始值設定項表達式中引用一個不是* compile-time constant *的枚舉類型的靜態字段是一個編譯時錯誤。這種類型的。”。 實際上,編譯器確實允許訪問枚舉構造函數中的statics字段,但僅適用于可以靜態計算(作為優化機制)的那些字段。 如果我們有:
enum Case {CASE_ONE,CASE_TWO,CASE_THREE;private static final int counter = 0;private int valueDependsOnCounter; Case() {this.valueDependsOnCounter = counter*counter;}}
,一切都會很好,因為編譯器可以預測計數器的初始化,可以在構造函數中使用它,構建枚舉實例,并將其分配給靜態最終CASE_ONE變量。 但是由于計數器取決于一些難以預測的計算,因此會引起錯誤。
為了使代碼仍然有效,有兩種解決方案:
1)將所需的靜態變量放在嵌套類中,然后從那里訪問它們:
class Nested {private static final int counter;static {int sum = 0;for(int i = 0; i<10; i++) {sum +=i;}counter = sum;}}enum Case {CASE_ONE,CASE_TWO,CASE_THREE;private static final int counter; private int valueDependsOnCounter; Case() {this.valueDependsOnCounter = Nested.counter*Nested.counter;}}
2)在構造函數中而不是在靜態塊中初始化(推薦):
enum Case {CASE_ONE, CASE_TWO,CASE_THREE; private static final int counter;private int valueDependsOnCounter; static {int sum = 0;for(int i = 0; i<10; i++) {sum +=i;}counter = sum;for(Case c : Case.values()) {c.valueDependsOnCounter = counter*counter;}}}
討論的異常甚至在JAVA規范文檔中指定。
參考: Transylvania JUG博客上的JCG合作伙伴 Attila-Mihaly Balazs的枚舉謎題 。
翻譯自: https://www.javacodegeeks.com/2012/04/java-enum-puzzler.html