【问题标题】:Java Enum Static Final Instance VariablesJava 枚举静态最终实例变量
【发布时间】:2011-06-22 05:22:41
【问题描述】:

嘘!

这段代码工作了一段时间,然后我决定添加一个默认颜色,但它停止工作了。我收到以下错误:

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 都决定抛出错误。 有什么想法吗?

【问题讨论】:

  • 有任何理由有一个defaultColor 字段吗?难道你的其余代码不应该只看Status.color吗?

标签: java static enums compiler-errors final


【解决方案1】:

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);
}

【讨论】:

    【解决方案2】:

    必须首先初始化枚举常量。要初始化它们,必须调用构造函数。第一个构造函数引用了一个在调用它时不可能初始化的静态字段。

    【讨论】:

      【解决方案3】:

      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 不在乎。安排 init 序列是程序员的工作,编译器检查所​​有损坏的 init 依赖项并不容易。无论如何,这个问题很容易解决:

      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());
          }
      

      【讨论】:

        【解决方案4】:

        【讨论】:

        • 您链接的错误是指访问枚举类的.class 文字,而不是引用枚举的实际静态字段。
        猜你喜欢
        • 2012-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-14
        相关资源
        最近更新 更多