2011-06-22 102 views
10

Huzzah!Java枚舉靜態最終實例變量

此代碼工作了一段時間,然後我決定添加一個默認顏色,並停止工作。我收到以下錯誤:

1 error found: 
File: Status.java [line: 20] 
Error: Status.java:20: illegal reference to static field from initializer 

在編譯時使用以下代碼。

import java.awt.Color; 

enum Status 
{ 
    OFF ("Off"), 
    TRAINING ("Training", new Color(255, 191, 128)), 
    BEGINNER ("Beginner", new Color(128, 255, 138)), 
    INTERMEDIATE ("Intermediate", new Color(128, 212, 255)), 
    ADVANCED ("Advanced", new Color(255, 128, 128)); 

    public final String name; 
    public final Color color; 

    public static final Color defaultColor = Color.WHITE; 

    Status(String name) 
    { 
    this(name, defaultColor); 
    } 
    Status(String name, Color color) 
    { 
    this.name = name; 
    this.color = color; 
    } 
} 

據我所知,這應該可行,但無論出於何種原因Java決定拋出一個錯誤。 有什麼想法?

+2

是否有任何理由有'defaultColor'字段?無論如何,你的代碼其餘部分是不是應該查看'Status.color'? –

回答

23

defaultColor只會被初始化後的構造函數被調用 - 因此它有它的默認值(NULL),直到那個時候。一個辦法是把默認的顏色在嵌套類型:

import java.awt.Color; 

enum Status 
{ 
    OFF ("Off"), 
    TRAINING ("Training", new Color(255, 191, 128)), 
    BEGINNER ("Beginner", new Color(128, 255, 138)), 
    INTERMEDIATE ("Intermediate", new Color(128, 212, 255)), 
    ADVANCED ("Advanced", new Color(255, 128, 128)); 

    public final String name; 
    public final Color color; 

    Status(String name) 
    { 
    this(name, Defaults.COLOR); 
    } 
    Status(String name, Color color) 
    { 
    this.name = name; 
    this.color = color; 
    } 

    private static class Defaults 
    { 
    private static Color COLOR = Color.WHITE; 
    } 
} 

當然,如果你只在代碼指的是默認的顏色一旦,你還不如內硬編碼構造函數調用:

Status(String name) 
{ 
    this(name, Color.WHITE); 
} 
10

枚舉常量必須先初始化。要初始化它們,必須調用構造函數。第一個構造函數引用一個靜態字段,它在被調用時可能不會被初始化。

6

Java允許這種

class Status 
{ 
    public static final Status OFF = new Status("Off"); 

    public static final Color defaultColor = Color.WHITE; 

    Status(String name) 
    { 
     this(name, defaultColor); 
    } 
} 

當然它必須在運行時的問題,但Java不關心。編程人員的工作是安排初始化序列,編譯器檢查所​​有破壞的初始化依賴關係並不容易。這個問題是很容易反正修復:

class Status 
{ 
    // now it works, this field is initialized first 
    public static final Color defaultColor = Color.WHITE; 

    public static final Status OFF = new Status("Off"); 

enum,這種解決方法並不適用,因爲在enum類型的靜態字段不能枚舉自己之前移動(可能是純語法的原因)。爲了避免混淆,Java爲enum添加了額外的限制 - 靜態字段不能從構造函數中引用。

這個限制是一半。從構造函數中檢查所有可能的靜態字段用法並不容易(如果不是不可能的話)。下面的代碼將編譯,擊敗限制:

enum Status 
{ 
    OFF("Off"); 

    public static final Color defaultColor = Color.WHITE; 
    static Color defaultColor(){ return defaultColor; } 

    Status(String name) 
    { 
     this(name, defaultColor()); 
    }