web-dev-qa-db-ja.com

タイプセーフ:ObjectからList <MyObject>への未チェックのキャスト

カスタムオブジェクトをリストするListViewがあります(MyObjectとしましょう)。

EditTextを使用して動的にフィルタリングしたいので、publishResultsメソッドを使用してgetFilter()を実装する必要がありました。

_@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    MyObjectAdapter.this.setItems((List<MyObject>) results.values);
    MyObjectAdapter.this.notifyDataSetChanged();
}
_

この時点で、Eclipseは不平を言います:_Type safety: Unchecked cast from Object to List<MyObject>_

このキャストは常に正しいと確信していますが、Eclipseは@SuppressWarnings("unchecked")の追加のみを提案していますが、SuppressWarningsは完全に反対です。

追加してみました:

_if(results.values instanceof List<MyObject>)
_

しかし、Eclipseは再び文句を言い、これは何も解決しません...

_Cannot perform instanceof check against parameterized type List<MyObject>. Use the form List<?>_

キャストは常に正しいことはわかっていますが、_results.values_が実際に_List<MyObject>_であることを確認するための適切な方法はどれですか。

前もって感謝します!

19
Eloi Navarro

さて、私は最終的に解決策を見つけることができました。

@ Medo42が言ったように:

別のオプションは、instanceofエラーが示すように、チェックしてリストにキャストすることです。次に、リスト内の要素を反復処理し、それらが実際にMyObjectのすべてのインスタンスであるかどうかを確認して、新しいリストにコピーできます。

この特定のケースを「警告なし」で機能させるために、まったく新しいオブジェクトを作成するプロセスはしていませんが、これは正しい方向でした。

@lokokoのアイデアを取り入れ、新しいsetItems()メソッドで使用しました。List<MyObject>ではなくObjectパラメータを使用して、

結果コードは次のとおりです。

public void setItems(List<MyObject> var){
    this.list = var;
}

public void setItems(Object var){
    List<MyObject> result = new ArrayList<MyObject>();
    if (var instanceof List){
        for(int i = 0; i < ((List<?>)var).size(); i++){
            Object item = ((List<?>) var).get(i);
            if(item instanceof MyObject){
                result.add((MyObject) item);
            }
        }
    }
    setItems(result);
}

皆さんの助けに感謝します!

12
Eloi Navarro

作業する必要があるのがObjectだけの場合、ジェネリック型MyObjectはコンパイルにのみ使用されるため、実際にList<MyObject>があることを実行時に確認することはできません。 -型チェック時not実行時に利用可能これが、instanceofチェックを追加しようとするとエラーになる理由です。

Objectが本当にList<MyObject>であることが確かな場合は、問題がないと確信できる理由を文書化すれば、@SuppressWarningsは大丈夫だと思います。

警告を絶対に避けたい場合は、独自のList実装(たとえば、MyObjectList)を作成し、それ自体は汎用的ではなくList<MyObject>を実装します。次に、実行時にinstanceofに対してMyObjectListチェックを実行できます。

もう1つのオプションは、instanceofエラーが示すように、List<?>を確認してキャストすることです。次に、リストの要素を繰り返し処理して、それらが実際にMyObjectのすべてのインスタンスであるかどうかを確認し、それらを新しいList<MyObject>にコピーします。

18
Medo42

このようなものを試してください:

List<?> result = (List<?>) results.values;
for (Object object : result) {
    if (object instanceof MyObject) {
        tempList.add((MyObject) object); // <-- add to temp
    }
}

filteredItems = tempList; // <-- set filtered
11
lokoko

setItems()に渡す前にチェックを実行できます。

_final Object myListObj = reuslts.values;
if(myListObj instanceof List<?>) {
    if(((List<?>)myListObj).get(0) instanceof MyObject)
        // You can safely suppress the warning here because you made sure it is a List containing MyObject
        MyObjectAdapter.this.setItems((List<? extends MyObject>) myListObj);

}
_

ただし、それに応じてsetItems()メソッドを変更する必要があります。

_public void setItems(List<? extends MyObject> list) {
    // Your code here
}
_
3
Lawrence Choy