Java 枚举静态最终实例变量

发布于 2024-11-16 14:14:24 字数 833 浏览 5 评论 0原文

好哇!

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

野稚 2024-11-23 14:14:24

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

defaultColor will only be initialized after the 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:

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);
}
痴情换悲伤 2024-11-23 14:14:24

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

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.

新一帅帅 2024-11-23 14:14:24

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

Java allows this

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:

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). To avoid confusion, Java adds an additional restriction for enum - static fields cannot be referenced from constructor.

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());
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文