Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Enum.values in with generic class extending Enum [duplicate]

I am trying to initialise a generic class with all the availables values from an Enum. HEre is how I would like it to work:

public class MyClass<E extends Enum<E>> {

    E[] choices;

    public MyClass() {
        choices = E.values();
    }

However, the call to E.values is not accepted in Eclipse saying that this method is undefined for this E.

Using this constructor instead is accepted, but requires the caller to provide the values:

public MyClass(E[] e) {
    choices = e;
}

In the documentation I found:

Java programming language enum types are much more powerful than their counterparts in other languages. The enum declaration defines a class (called an enum type). The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.

Is there a way to workaround this issue ?

like image 937
Olivier.Roger Avatar asked Jul 26 '12 06:07

Olivier.Roger


People also ask

Can enum extend enum?

No, we cannot extend an enum in Java. Java enums can extend java. lang. Enum class implicitly, so enum types cannot extend another class.

Can enums extend each other?

Enum and has several static members. Therefore enum cannot extend any other class or enum: there is no multiple inheritance. Class cannot extend enum as well. This limitation is enforced by compiler.

Can enum be generic?

However, it is possible to use enums in generics. The MSDN article for Enum gives the following type definition for the class Enum . This definition can be used to get enum s working as generic types by constraining the generic type to those of Enum .

Can an enum inherit from another enum?

Enums cannot inherit from other enums. In fact all enums must actually inherit from System. Enum . C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.


2 Answers

Your best option is probably to pass a Class of the desired enum to the constructor. (See how an EnumMap is constructed for instance.)

You can then use clazz.getEnumConstants() to get hold of the constants.

like image 72
aioobe Avatar answered Oct 12 '22 12:10

aioobe


Your first code snippet doesn't work because of how Generics is implemented in Java, and due to a phenomenon known as type erasure. Because of this, the JVM will have no idea what the type of E is when your program is executing.

You could probably do something like this in MyClass's constructor:

public MyClass(E type) {
    choices = type.getDeclaringClass().getEnumConstants();
}
like image 41
Jeshurun Avatar answered Oct 12 '22 13:10

Jeshurun