Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Method With Bounded Extends Enum Parameter - Cannot Access values() method

I would like to write a generic method that takes a bounded parameter that extends Enum. For example, if I have an Enum as follows:

public enum InputFlags{
    ONE (0000001),
    TWO (0000002),
    THREE (00000004);

    public final int value;

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

I can then do the following:

for (InputFlags ifg : InputFlags.values()){
            // Do something with ifg
}

However if I try to do the above in a generic method whose return parameter is bounded, I cannot access the values() method:

public static <T extends Enum> T getFlags(int f){
        T.values(); // NOT allowed, even though I have bounded by extending Enum.
}

It seems as though I cannot access values() in the generic method. Is this a peculiarity of Enums or is there a way round this?

like image 597
D-Dᴙum Avatar asked Jan 11 '15 22:01

D-Dᴙum


2 Answers

values() is a very strange thing in Java. Look in the documentation for Enum - values() isn't even there! values() is not a method of Enum at all. Instead a static method called values() is implicitly added to every class extending Enum. But the values() method for one enum is different from the values() method in another enum.

The fact that T extends Enum means that if t has type T you can call instance methods from Enum on t. You can't call static methods of Enum (and even if you could, values() doesn't exist anyway!)

values() is only useful when you know the actual enum by name. It cannot be used when you only have a type parameter T.

The way around this problem is to pass a Class object. Like this:

public static <T extends Enum<T>> T getFlags(Class<T> clazz, int f){
    T[] array = clazz.getEnumConstants();  // This is how you can get an array.
    Set<T> set = EnumSet.allOf(clazz);     // This is how you can get a Set.     
}
like image 137
Paul Boddington Avatar answered Oct 21 '22 03:10

Paul Boddington


values() is a static method inserted by the compiler in the InputFlags class. Thus, it is not possible to use T.values(), especially since T is a generic type. However, if you can get the Class object of T (usually via getClass(), or by passing it to getFlags(int f, Class<T> clazz)), you can use Class#getEnumConstants() on that object.

like image 23
Clashsoft Avatar answered Oct 21 '22 02:10

Clashsoft