简体   繁体   English

Java Enum静态最终实例变量

[英]Java Enum Static Final Instance Variables

Huzzah! 好哇!

This code worked for a time, then I decided to add a default color, and it stopped working. 这段代码工作了一段时间,然后我决定添加一个默认颜色,它停止工作。 I get the following error: 我收到以下错误:

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

With the following code at compile-time. 在编译时使用以下代码。

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

This should work, as far as I can tell, but for whatever reason Java decided to throw an error. 据我所知,这应该可以工作,但无论出于什么原因,Java决定抛出一个错误。 Any thoughts? 有什么想法吗?

defaultColor will only be initialized after the constructors have been called - so it will have its default value (null) until that time. defaultColor只会在调用构造函数初始化 - 因此在此之前它将具有默认值(null)。 One option would be to put the default colour in a nested type: 一种选择是将默认颜色放在嵌套类型中:

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

Of course, if you're only referring to the default colour once in the code, you might as well hard-code it within the constructor call: 当然,如果您只在代码中引用一次默认颜色,那么您也可以在构造函数调用中对其进行硬编码:

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

The enum constants have to be initialized first. 必须首先初始化枚举常量。 To initialize them, the constructors must be called. 要初始化它们,必须调用构造函数。 The first constructor references a static field that could not possibly have been initialized at the time it is called. 第一个构造函数引用一个静态字段,该字段在调用时可能无法初始化。

Java allows this Java允许这样做

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

    public static final Color defaultColor = Color.WHITE;

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

Of course it'll have problem at runtime, but Java doesn't care. 当然它在运行时会有问题,但Java并不关心。 It's the job of the programmer to arrange init sequences, and it is not easy for compiler to check all broken init dependencies. 程序员的工作是安排init序列,编译器检查所​​有破坏的init依赖项并不容易。 The problem is easy to fix anyway: 无论如何,问题很容易解决:

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

But for enum , this workaround does not apply, because the static fields in an enum type cannot be moved before enums themselves (probably for pure syntactic reason). 但是对于enum ,这种解决方法不适用,因为enum类型中的静态字段在enum之前无法移动(可能出于纯语法原因)。 To avoid confusion, Java adds an additional restriction for enum - static fields cannot be referenced from constructor. 为了避免混淆,Java为enum添加了一个额外的限制 - 静态字段不能从构造函数中引用。

This restriction is half-assed. 这种限制是半生的。 It's not easy (if not impossible) to check all possible usages of static fields from constructor. 从构造函数中检查静态字段的所有可能用法并不容易(如果不是不可能)。 The following code would compile, defeating the restriction: 以下代码将编译,击败限制:

enum Status
{
    OFF("Off");

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM