我很久没有编码了,并且用通配符失去了控制力。
我有这个整洁的小功能,效果很好
public static <T> ArrayList<T> GetObjects(List<?> list, Class<T> c){
ArrayList<T> objects = new ArrayList();
for(Object o : list){
if(c.isInstance(o)){
objects.add(c.cast(o));
}
}
return objects;
}
但是我希望它能够接受类列表并执行类似的操作
public static <T> ArrayList<T> GetMultipleObjects(List<?> list, List<Class<T>> classes){
ArrayList<T> objects = new ArrayList();
for(Object o : list){
for(Class c : classes){
if(c.isInstance(o)){
objects.add(c.cast(o));
}
}
}
return objects;
}
事后看来,这显然是不可能的。
答案 0 :(得分:1)
路易斯在评论中是正确的:在Java中定义这个函数没有合理的方法。
Java没有析取类型 - 也就是说,没有办法表达类似&#34; String
或Integer
&#的类型的概念34 ;.你最接近的是找到一个共同的超类型 - 因为所有可实例化的类型都继承自Object
(模数基元,但让我们暂时将它们放在一边),你总是可以找到一个常见的超类型,虽然它可能只是Object
,但通常不是很有用。
为了说明为什么会出现这种情况,请考虑一下这个功能可以用于什么类型的事情。我看到两个案例:
案例1 :您希望过滤到类型是一个或多个类型的子类型的位置,这些类型都共享一个共同的超类型,并返回超类型的列表。您可以通过将通配符类型与类型参数一起使用来轻松完成此操作:
public static <T> List<T> filter(
List<?> input,
List<? extends Class<? extends T>> subtypesOfT) {
// implementation exactly as you have it
}
但在大多数情况下,这相当于只使用原始函数并传递超类型。例如。使用原始功能,您只需传递Number.class
并返回List<Number>
,其中列表中的值可以是Double
或Integer
或Float
。唯一有用的方法是,如果您想从List<Number>
过滤出List<?>
,但也只包含 Number
的某些子类型。例如您可以通过asList(Double.class, Integer.class)
并返回List<Number>
。但我怀疑这会特别有用,特别是在这种形式的一般情况下。
案例2 :或者,您可以考虑采用List<?>
并过滤它以仅包含任意一组其他类型的值。在这种情况下,除非您计算一个,否则没有T
统一,所以您可以做的最好的事情是返回List<Object>
(或者,如果列表是只读的,则等效于此情况,一个List<?>
)。为此,您根本不需要该方法是通用的:只需使用ArrayList<Object>
来构造返回值,它就可以正常工作。
如果您以足够的元编程方式执行此操作,您可能希望有一种方法来构建List<T>
,其中T
是所有值的最具体的常见超类型List<?>
可以分配给。这也是可行的,但您首先需要找到T
。这是你可以做到的一种方式:
private static Class<?> findCommonSupertype(List<Class<?>> types) {
Class<?> result = types.get(0);
for (Class<?> type : types) {
// Keep going as long as result is a supertype of the current type.
if (result.isAssignableFrom(type)) {
continue;
}
// Skip interfaces since they unify with any class type (unless
// the class is final, which we don't check for here).
if (result.isInterface() && !type.isInterface()) {
result = type;
} else if (type.isInterface()) {
continue;
}
// Otherwise, scan up through the inheritance hierarchy to find a
// new type that can serve as a common supertype for type and result.
Class<?> supertype = type;
while (!supertype.isAssignableFrom(result)) {
supertype = supertype.getSuperclass();
if (supertype == null) {
throw new IllegalArgumentException(
type + " and " + result + " do not share a common supertype");
}
}
result = supertype;
}
return result;
}
尽管如此,即使你有这样的功能,它仍然不会特别有用,因为你可以建立一个List<T>
,但你不能静态地知道T
1}}是(因为它会动态计算),所以我不认为这是你真正想要的。