施加这样的编译时限制是不可能的。泛型类型参数是引用类型的替身;它们不区分类类型和接口类型。类型参数声明中的附加边界必须是接口类型这一事实只是偶然的 - 您利用它作为将类型归为接口的手段的策略很聪明,但是由于不能使用类型参数的限制而失败了在多个范围内。
Class.isInterface()
您唯一的选择是像 Louis Wasserman指出的那样满足运行时检查,或者让调用者对其传入的内容负责。无论哪种方式,请确保清楚地记录方法的期望和行为。
B
旨在作为通配符的占位符,以便客户端可以获得既是 aSomeClass
又是 a 的单个对象,A
而无需基于信任进行强制转换。客户端将无权访问实现的实际类的名称,SomeClass
并且A
这对我来说似乎很矛盾。B
如果调用者不可能知道它的评估结果,那么声明它是没有意义的。请记住:泛型方法的调用者提供其类型参数。因此,调用者B
在没有任何依据的情况下做出决定只能是猜测——而这永远不可能是类型安全的。
看起来您真正希望您的方法返回的是某种既是 aSomeClass
又是 an 的类型A
,但这很棘手,因为它们不共享一个共同的超类型:
public static <A> SomeClass&A makeSomeClass(A thing) {...}
(这只是用于演示目的的无意义语法)
作为一种解决方法,请考虑表示 aSomeClass
和某些接口类型的替代方法。例如,候选接口可以有一个返回 a 的通用方法SomeClass
:
public interface IsSomeClass {
SomeClass asSomeClass();
}
public interface Foo extends IsSomeClass { }
的实现asSomeClass
实际上只是 return this
。然后你可以这样做:
public static <A extends IsSomeClass> A makeSomeClass(Class<A> type) {...}
并且该方法的调用者将能够使用返回的对象作为任一类型:
final Foo foo = makeSomeClass(Foo.class);
final SomeClass someClass = foo.asSomeClass();
如果接口本身不能修改,那么另一种选择是使用包装类和组合:
final class SomeClassWrapper<A> {
private final SomeClass someClass;
private final A a;
//constructor and getters, etc.
}
而您的方法将返回一个包装器实例,将实现实例分配给 someClass
and a
:
public static <A> SomeClassWrapper<A> makeSomeClass(Class<A> type) {...}