JDK-6708424 : (reflect) Class.isEnum() returns useless values for anonymous enum values
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux,windows_xp
  • CPU: x86
  • Submitted: 2008-05-29
  • Updated: 2012-09-28
  • Resolved: 2008-05-29
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_05"
Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Class.isEnum() should return true for any enum value declared using the enum statement. If the enum is declared anonymously, it returns false. The documentation for isEnum() states this: "Returns true if and only if this class was declared as an enum in the source code." This is a bit ambiguous, since for an anonymous inner class in an enum, it was declared using the enum keyword (meaning it didn't merely extend the Enum class). As a user, what I'm looking for is a way to distinguish enum constants from other objects, so I need isEnum() to return true for all enum constants, even if they anonymously override something.

If this method is behaving as intended, then we need another method (isEnumConstant()?) to identify enum constants, and we need the documentation of this class clarified. (I suspect that most people, if they bother to read the method description at all for a method with such an obvious purpose, wouldn't think of anonymous inner classes.) Either way, the way isEnum() is written, it doesn't help me.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the class and look at the results of isEnum() for each constant. It will print out the value of isEnum() for each constant.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All constants should return true for isEnum().
ACTUAL -
The third constant returns false for isEnum().

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public enum EnumBug {
  Alpha(3),
  Beta(6),
  Delta(4) {
    @Override public int getValue() { return -1; }

    @Override public String toString() { return "Gamma"; }
  },
  Epsilon(9);

  private int value;

  EnumBug(int value) { this.value = value; }

  public int getValue() { return this.value; }

  public static boolean isEnumWorkaround(Class enumClass) {
    while ( enumClass.isAnonymousClass() ) {
      enumClass = enumClass.getSuperclass();
    }
    return enumClass.isEnum();
  }

  public static void main(String[] args) {
    for ( EnumBug thing : EnumBug.values() ) {
      String nameString = thing + " (" + thing.name() + ")";
      System.out.println( String.format(
          "%-18s isEnum = %-5b [workaround isEnum = %b]", nameString,
          thing.getClass().isEnum(), isEnumWorkaround( thing.getClass() ) ) );
    }
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
  public static boolean isEnumWorkaround(Class enumClass) {
    while ( enumClass.isAnonymousClass() ) {
      enumClass = enumClass.getSuperclass();
    }
    return enumClass.isEnum();
  }

Comments
EVALUATION The Class.isEnum method is behaving as intended, see bug 5020490. The anonymous inner classes used to implement enum constants are not themselves enum classes. To get the effective class of an enum object regardless of whether or not a specialized enum constant is used in the implementation, use the method getDeclaringClass() inherited from java.lang.Enum. Given an arbitrary object, it will have to be poked at a bit to see if it is an enum constant.
29-05-2008