ライブラリを探している場合、私が最初に考えたのは、次のように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;
}
型キャストの警告に対する嫌悪感によっては、3 つのオプションすべてでキャスト演算子を削除することもできます。
コメントごと
の編集 次の変更/改善がコメントで提案されました。
オプション 1 の改善:
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;
}
オプション 2 の改善:
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;
}
オプション 3 の改善:
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 の例はかなり輝いています。静的インポートを気にしなければ、どちらの Guava の例も非常に読みやすくなります。