简体   繁体   中英

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?

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.     
}

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.

This is a peculiarity of static methods. There is no way in Java, with generics or otherwise, to define an interface that applies to static methods, ie. that a class should/must implement a static method.

Also, type erasure (among other things) prevents you from using a type variable T as a type name in a static method invocation expression.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM