Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 832
skeggse Avatar asked Jun 22 '11 05:06

skeggse


People also ask

Can enum have static variables?

An enum can, just like a class , have attributes and methods. The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden). An enum cannot be used to create objects, and it cannot extend other classes (but it can implement interfaces).

Are enums implicitly static and final?

An enum declaration is implicitly final unless it contains at least one enum constant that has a class body. A nested enum type is implicitly static.

Is enum static by default Java?

Yes, enums are effectively static.

Can enum have instance variables?

Enums are very powerful as they may have instance variables, instance methods, and constructors. Each enum constant should be written in capital letters. Every enum constant is by default internally public static final of type Enum declared.


1 Answers

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);
}
like image 54
Jon Skeet Avatar answered Oct 09 '22 07:10

Jon Skeet