第一点:您可以通过将Class c
参数替换为Class<T> c
. 这可能就是你所需要的......在这种情况下...... =:-)
第二点:通常调用 SomeContainer.subset() 的代码会在编译类型时知道类型 U (来自逻辑上下文)。这一定是你的情况,否则你将无法传递Class c
参数。
尝试:
class SomeContainer<T> extends ArrayList<T>{
public <U extends T> SomeContainer subset(Class<U> c){
SomeContainer<U> output = new SomeContainer<U>();
// put filtered elements into output
return output;
}
}
看看我在那里做了什么?
在方法调用中引入了第二种类型的参数:U extends T
. 在与 的论点中也使用了这个Class<U> c
。
调用者会像这样调用(其中 X 被选择为 T 的子类):
SomeContainer<X> mySubset = mySomeContainer.subset(X.class); // type inference
SomeContainer<X> mySubset = mySomeContainer.<X>subset(X.class); // type arg specified
如果您需要比这更动态的东西,通配符可以提供帮助 - 允许传入和传出参数化类型的“家族”:
public SomeContainer<? extends X> subset(Class<? extends X> c){
这是一个“塑料”函数接口:您可以返回SomeContainer<T>
或SomeContainer<X>
为任何作为 T 子类的 X。以下也适用:
public SomeContainer<? super Z> subset(Class<? extends X> c){
然而,正如另一位发帖人所说,泛型是一种编译时构造,它们在编译期间被生成的非泛型代码替换。这意味着您不能用一行代码动态决定用于实例化泛型类型的类型。但是你可以作弊:如果 T 的子类数量有限,比如 X、Y 和 Z,其中 Z 扩展 Y,Y 扩展 Z,那么你可以使用一个古老的 hacky “if 语句”。尝试:
类 SomeContainer 扩展 ArrayList{
public SomeContainer<? extends X> subset(Class<? extends X> c){
SomeContainer<? extends X> output = null;
// would like to use: "if (c instance of Class<Z>)"
// but instanceof does not allow generic type arguments
if (c.getName().equals(Z.class.getName())) {
SomeContainer<Z> outputZ = new SomeContainer<Z>();
// put filtered elements into outputZ
output = outputZ;
} else if (c.getName().equals(Y.class.getName())) {
SomeContainer<Y> outputY = new SomeContainer<Y>();
// put filtered elements into outputZ
output = outputY;
} else if (c.getName().equals(X.class.getName())) {
SomeContainer<X> outputX = new SomeContainer<X>();
// put filtered elements into outputZ
output = outputX;
}
return output;
}
}
简单的!(或不)=:-)