将运行时解析参数传递给具有多个绑定类型的方法,编译错误



我有一个方法,看起来像这样:

public static <T extends Enum<T> & Marshallable> String foo(Collection<T> collection, Class<? extends Marshallable>... marshallables);

所以我期望传递的集合是一个Enum实现可Marshallable接口。如果我在运行时有具体的Enum类型,它可以正常工作,但我写了一个测试方法,从类对象动态创建一个Enum列表(实现Marshallable),并且我在将此列表传递到上面的方法时遇到麻烦。

@Test
public void fooTest() {
...
if (clazz.isEnum()) { // collection enum xml
    List<? extends Enum<? extends Marshallable>> enumList = (List<? extends Enum<? extends Marshallable>>) Arrays.asList(clazz.getEnumConstants());
--> String enumListXml = foo(enumList, clazz);
...

标记行会导致编译错误。我不知道如何在不改变方法签名的情况下传递列表。

您需要使用带有未检查强制转换的泛型助手方法:

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);
    }
}

你的版本不能工作的原因是T extends Enum<T> & Marshallable, T是递归绑定的-只能用类型参数表示。? extends Enum<? extends Marshallable>中的通配符类型参数不再指定这种关系。

警告: fooHelper不返回包含T的类型是必要的,因为这可能导致堆污染。例如:

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

最新更新