如果您正在寻找图书馆,我的第一个想法是使用Google Guava Libraries,如下所示:
public <T, U extends T> List<U> homogenize(List<T> list, final Class<U> subclass) {
Predicate<T> pred = new Predicate<T>() {
@Override
public boolean apply(T input) {
return input.getClass().isAssignableFrom(subclass);
}
};
return Iterables.all(list, pred) ? (List<U>)list : null;
}
我还没有尝试过,以确保扭结已经消失。然而,我看着它,并认为它非常丑陋。稍微好一点的番石榴方法是:
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
Iterable<U> ret = Iterables.filter(list, subclass);
if (list.size() != Lists.newArrayList(ret).size()) return null;
return (List<U>)list;
}
但是,它仍然有点难看。它使用集合的内部副本。它仍然返回原始的演员视图。毕竟,最干净的方法似乎是使用常规 Java:
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
for( T t : list) {
if (!t.getClass().isAssignableFrom(subclass)) return null;
}
return (List<U>)list;
}
根据您对类型转换警告的反感,您甚至可以在所有三个选项中删除转换运算符。
根据评论进行编辑评论
中提出了以下更改/改进。
选项一改进:
public <T, U extends T> List<U> homogenize(List<T> list, final Class<U> subclass) {
return Iterables.all(list, Predicates.instanceOf(subclass)) ? (List<U>)list : null;
}
选项二改进:
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
Iterable<U> ret = Iterables.filter(list, subclass);
return (list.size() != Iterables.size(ret)) ? null : (List<U>)list;
}
选项三改进:
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
for( T t : list) {
if (!subclass.isInstance(t.getClass())) return null;
}
return (List<U>)list;
}
通过这些改进,第一个番石榴示例大放异彩。如果您不介意静态导入,则两个 Guava 示例都变得非常易读。