将运行时解析参数传递给具有多个绑定类型的编译错误的方法 [英] Passing a runtime resolved parameter to a method which has multiple bound type, compilation error
问题描述
我有一个如下所示的方法:
public static< T extends Enum< T> &安培; Marshallable> String foo(Collection< T> collection,Class< ;? extends Marshallable> ... marshallables);
所以我期待收集的是一个Enum实现的Marshallable接口。
如果我在运行时具有具体的Enum类型,但是我写了一个测试方法,它会从类对象中动态创建一个Enum列表(实现Marshallable),并且无法将此列表传递给上面的方法。 p>
@Test
public void fooTest(){
...
if(clazz.isEnum ()){// collection enum xml
List< ;?扩展Enum <?扩展可编排>> 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()){
//这是安全的,因为isEnum检查,我们不返回任何
//带有T的类型(重要的是因为调用者可以指定T是什么)。
@SuppressWarnings(unchecked)
final Class< T> enumType =(Class< T>)类型;
最终列表< T> enumConstants = Arrays.asList(enumType.getEnumConstants());
foo(enumConstants);
$ b $ p
$ b你的版本不起作用的原因是因为
T扩展Enum< T> &安培;可控制的
,T
是递归绑定的 - 只能用类型参数表示。中的通配符类型参数?扩展Enum <?
警告:
T
的类型,因为这可能会导致堆污染。例如:
private static< T extends Enum< T> &安培; Marshallable>列表与LT; T> unsafeFooHelper(Class< ;? extends Marshallable> type){
if(type.isEnum()){
//不再安全!
@SuppressWarnings(unchecked)
final Class< T> enumType =(Class< T>)类型;
返回Arrays.asList(enumType.getEnumConstants());
}
返回Collections.emptyList();
}
enum Enum1实现了Marshallable {ONE,TWO}
枚举Enum2实现了Marshallable {A,B}
...
//关于T是什么的调用者谎言:
List< Enum2> enumConstants = Main。< Enum2> unsafeFooHelper(Enum1.class);
//稍后...
Enum2 enumConstant = enumConstants.get(0); // ClassCastException
I have a method which looks like this:
public static <T extends Enum<T> & Marshallable> String foo(Collection<T> collection, Class<? extends Marshallable>... marshallables);
So I'm expecting the collection passed to be a Enum implementing Marshallable interface. It works fine if I have the concrete Enum types at runtime but I wrote a test method which creates an Enum list(implementing Marshallable) dynamically from class object, and I am having trouble passing this list into method above.
@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); ...
Marked line will give compilation error. I couldn't figure out how to pass the list without changing method signatures.
解决方案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 containingT
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
这篇关于将运行时解析参数传递给具有多个绑定类型的编译错误的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!