Shadow Man
Shadow Man

Reputation: 3402

Generic Enum in a Collection or vararg parameter

I'm trying to create a collection of enum classes so that I can iterate through the collection and then iterate through the enum values by calling enumClass.getEnumConstants().

Given the following:

public interface MyEnumType {
   String getSubtype ();
}

public enum MyEnumTypeA implements MyEnumType {
   A_1,
   A_2;
   public String getSubtype () { return "A"; }
}

public enum MyEnumTypeB implements MyEnumType {
   B_1,
   B_2;
   public String getSubtype () { return "B"; }
}

I've tried using varargs:

private <T extends Enum<T> & MyEnumType> void handleTypes (
   Class<? extends T>... enumTypes )
{
   for( Class<? extends T> enumType : enumTypes )
      for( T value : enumType.getEnumConstants() )
         handleValue( value );
}

private void doStuff () {
   // error here
   handleTypes( MyEnumTypeA.class, MyEnumTypeB.class );
}

...but using wild-card generics in varargs produces a compilation error whenever I try to call the function

I've also tried building a List:

public class MyMainClass
{
   private static Collection<Class<Enum<? extends MyEnumType>>> ALL_TYPES
      = Lists.newArrayList();
   {
      // error here
      ALL_TYPES.add( MyEnumTypeA.class );
      ALL_TYPES.add( MyEnumTypeB.class );
   }
}

...but this too fails to compile when I try to add to the list.

The following works but requires a cast (no compilation errors or warnings if I passed in Object.class):

private void runNoMatchTests ( Class... enumTypes ) {
   for( Class enumType : enumTypes ) {
      for( MyEnumType value : ( (Class<MyEnumType>)enumType ).getEnumConstants() ) {
         handleValue( value );
      }
   }
}

How can this be done without using a cast? Can it be done without using a cast?

Upvotes: 1

Views: 569

Answers (1)

andersschuller
andersschuller

Reputation: 13907

I'm not completely sure why this is the case, but your first attempt can compile if you change <T extends Enum<T> & MyEnumType> to <T extends Enum<?> & MyEnumType> as shown below:

private <T extends Enum<?> & MyEnumType> void handleTypes(Class<? extends T>... enumTypes) {
    ...
}

Upvotes: 1

Related Questions