我有一个Class<?>
类型的对象,我正在尝试使用签名的方法:
<T extends A & B> void foo(Class<T> clazz);
如何声明参数以满足签名?
示例:
void bar(String type) throws Exception {
Class<?> clazz = Class.forName(type);
if(!clazz.isAssignableFrom(A.class)) throw new IllegalArgumentException("type="+type);
if(!clazz.isAssignableFrom(B.class)) throw new IllegalArgumentException("type="+type);
//We know clazz implements both A and B, how do we call foo?
foo(clazz.asSubclass(???));
}
<T extends A & B> void foo(Class<T> clazz) {
//Success
}
编辑:我将foo
方法重构为<T extends A> ...
并将其中的.isAssignableFrom(B.class)
移动到其中。
答案 0 :(得分:1)
编辑:让我以此为前提(请参见下文以获取更多信息):反射和泛型并不适合,因为它们在不同的时间运行:
resolveClass()
),由于类型擦除,大多数泛型信息在运行时会丢失原始答案:
T extends A & B
仅在B
是一个接口(A可以是一个类或一个接口)并且参数必须匹配两者(即它必须是A
并实施B
(假设A
尚未实施B
,在这种情况下,A & B
部分将是不必要的)。
作为示例,我们使用Number
和Comparable
:
<T extends Number & Comparable<T>> void foo(Class<T> clazz);
我们现在可以叫foo(Long.class)
,因为Long extends Number implements Comparable<Long>
。
我们无法调用foo(AtomicInteger.class)
,因为AtomicInteger extends Number
但是它没有实现Comparable<AtomicInteger>
。
我们也无法调用foo(Number.class)
,因为Number
匹配extends Number
但未实现Comparable<Number>
。
在您的情况下,您需要定义一个变量Class<? extends A & B>
,但不支持,因此您需要使用通用类型(在调用方法或类上定义) )或具体类型:
<T extends A & B> bar() {
Class<T> clazz = resolveClass(); //This would need the same generic type
foo( clazz );
}
或
class C extends A implements B {}
和
Class<C> clazz = resolveClass(); //This would need the same generic type
foo( clazz );
您可以想象这会变得非常复杂,可能不可行。 作为最后的尝试,您可以尝试使用原始类型:
Class clazz = resolveClass(); //This would need the same generic type
foo( clazz );
这会产生很多警告,因为它会禁用类型检查,因此请确保对您的参数进行了彻底检查。因此,如果您需要这样做,则可能暗示存在设计缺陷,因此,我建议您认真考虑是否需要T extends A & B
以及代码在做什么。