我有一个看起来像这样的方法:
public static <T extends Enum<T> & Marshallable> String foo(Collection<T> collection, Class<? extends Marshallable>... marshallables);
Run Code Online (Sandbox Code Playgroud)
所以我期待传递的集合是一个实现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);
...
Run Code Online (Sandbox Code Playgroud)
标记的行将给出编译错误.我无法弄清楚如何在不更改方法签名的情况下传递列表.
您需要使用未经检查的强制转换的通用辅助方法:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
你的版本不起作用的原因是因为with 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
506 次 |
| 最近记录: |