7

Recently, I've noticed, it is possible to have:

class Test {
    public enum Season { WINTER, SPRING, SUMMER, FALL }
    Season field = Season.WINTER.SPRING; // why is WINTER.SPRING possible?
}

Is there a reason for this?

John Assymptoth
  • 8,227
  • 12
  • 49
  • 68

2 Answers2

10

When you access a static member of an object (including enums) in Java, the compiler effectively replaces the object with its static type. More concretely,

class ExampleClass {
    static int staticField;
    static void staticMethod() {
        ExampleClass example = new ExampleClass();
        example.staticField;     // Equivalent to ExampleClass.staticField;
        example.staticMethod();  // Equivalent to ExampleClass.staticMethod();
    }
}

Similarly, since enums are effectively "static", Season.WINTER.SPRING is equivalent to Season.SPRING; Season.WINTER is replaced with its enum type Season.

As a side note, accessing static members from instances is discouraged because it can be quite confusing. For example, if you saw a piece of code that contained someThread.sleep(), you might be tricked into believing that someThread is put to sleep. However, since sleep() is static, that code is actually invoking Thread.sleep() which sleeps the current thread.

ide
  • 19,942
  • 5
  • 64
  • 106
  • I recommend turning on warnings for static access (Eclipse has this option, other IDEs probably do too). I always fix those warnings for that specific reason: they are confusing, and can mislead whomever is reading the code into thinking the program is doing something it is not. –  Jan 20 '11 at 01:05
1

It's because enums are kind of special classes. If we take a look at the fields inside of Season.WINTER, for example:

  for (Field field : Test.Season.WINTER.getClass().getFields())
   System.out.println(field);

We'll see as output:

public static final TestEnum$Test$Season TestEnum$Test$Season.WINTER
public static final TestEnum$Test$Season TestEnum$Test$Season.SPRING
public static final TestEnum$Test$Season TestEnum$Test$Season.SUMMER
public static final TestEnum$Test$Season TestEnum$Test$Season.FALL

So each enum value is actually also a static constant of the enum class, Season, and so have access to Season's static fields, or the other enum values (including itself).

However, it's probably better to just access the enum values directly from the enum, like Season.SPRING, since it's simpler and less likely to confuse someone reading your code.

Zach L
  • 16,072
  • 4
  • 38
  • 39