Java 枚举静态最终实例变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6435267/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 05:53:44  来源:igfitidea点击:

Java Enum Static Final Instance Variables

javastaticenumscompiler-errorsfinal

提问by skeggse

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. Any thoughts?

据我所知,这应该有效,但无论出于何种原因,Java 决定抛出错误。有什么想法吗?

采纳答案by Jon Skeet

defaultColorwill only be initialized afterthe constructors have been called - so it will have its default value (null) until that time. One option would be to put the default colour in a nested type:

defaultColor只会在构造函数被调用初始化- 所以在那个时候它会有它的默认值(空)。一种选择是将默认颜色放在嵌套类型中:

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 oncein the code, you might as well hard-code it within the constructor call:

当然,如果您只在代码中引用一次默认颜色,您也可以在构造函数调用中对其进行硬编码:

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

回答by ColinD

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.

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

回答by irreputable

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. It's the job of the programmer to arrange init sequences, and it is not easy for compiler to check all broken init dependencies. The problem is easy to fix anyway:

当然它在运行时会有问题,但 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");

But for enum, this workaround does not apply, because the static fields in an enumtype cannot be moved before enums themselves (probably for pure syntactic reason). To avoid confusion, Java adds an additional restriction for enum- static fields cannot be referenced from constructor.

但是对于enum,这种解决方法不适用,因为enum在枚举本身之前不能移动类型中的静态字段(可能是出于纯粹的语法原因)。为了避免混淆,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());
    }