You'll need to use a generic helper method with an unchecked cast:
private static <T extends Enum<T> & Marshallable> void fooHelper(Class<? extends Marshallable> type) {
if (type.isEnum()) {
//This is safe because of the isEnum check, and we don't return any
//type with T (important because the caller can specify what T is).
@SuppressWarnings("unchecked")
final Class<T> enumType = (Class<T>)type;
final List<T> enumConstants = Arrays.asList(enumType.getEnumConstants());
foo(enumConstants);
}
}
The reason your version doesn't work is because with T extends Enum<T> & Marshallable
, T
is recursively bound - something that can only be expressed with type parameters. The wildcard type arguments in ? extends Enum<? extends Marshallable>
no longer specify that relationship.
WARNING: It's imperative that fooHelper
doesn't return a type containing T
because this could cause heap pollution. For example:
private static <T extends Enum<T> & Marshallable> List<T> unsafeFooHelper(Class<? extends Marshallable> type) {
if (type.isEnum()) {
//no longer safe!
@SuppressWarnings("unchecked")
final Class<T> enumType = (Class<T>)type;
return Arrays.asList(enumType.getEnumConstants());
}
return Collections.emptyList();
}
enum Enum1 implements Marshallable { ONE, TWO }
enum Enum2 implements Marshallable { A, B }
...
//caller lies about what T is:
List<Enum2> enumConstants = Main.<Enum2>unsafeFooHelper(Enum1.class);
//sometime later...
Enum2 enumConstant = enumConstants.get(0); //ClassCastException
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…