2011-06-22 65 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()); 
    }