web-dev-qa-db-ja.com

java:未チェックのキャスト警告を修正する方法

私は次のコードを持っています:

_private HashMap<Class<?>, HashMap<Entity, ? extends Component>> m_componentStores;

public <T extends Component> T getComponent(Entity e, Class<T> exampleClass)
{
    HashMap<Entity, ? extends Component> store = m_componentStores.get(exampleClass);

    T result = (T)store.get(e);

    if (result == null)
    {
        throw new IllegalArgumentException( "GET FAIL: "+e+" does not possess Component of class\nmissing: "+exampleClass );
    }

    return result;
}
_

コンパイルすると、T result = (T)store.get(e)に未チェックのキャストがあることがわかります。

_Type safety: Unchecked cast from capture#2-of ? extends Component to T
_

この警告が表示されないようにするには何が欠けていますか?

24
Brad

Class.castはあなたが欲しいものです。さて、あなたは反射を使用しないことを検討するかもしれません。

行を変更します。

T result = (T)store.get(e);

に:

T result = exampleClass.cast(store.get(e));
40

Castステートメントの上に@SuppressWarnings("unchecked")を記述します。

@SuppressWarnings("unchecked")
T result = (T)store.get(e);

警告を無視しても安全である理由を説明する説明を追加します。

16
Ralph

ジェネリックのextendsは、実際にはそのようには機能しません。 T!= _? extends Component_であっても_T extends Component_。あなたが持っているものは実際には ワイルドカードキャプチャ であり、それは別の目的を持っています。

そして、はい、あなたのソリューションはタイプセーフではありません-以下の2つの_?_マークの間に関係はありません:

_    private HashMap<Class<?>, HashMap<Entity, ? extends Component>> m_componentStores;
_

そのため、キーとしてComponentのサブクラスのインスタンスをこの構造体に配置することは、他のクラス(Componentのサブクラスでさえも)を使用することもできます。

ジェネリック型はコンパイル時でのみ解決されるため、実行時_m_componentStores_には、extendsComponent以外に、そこにある値の正確なタイプを知る方法がありません。

したがって、store.get(e)から取得する型は... Componentです。

_    Component result = store.get(e);
_

ComponentTにキャストすると、キャストを静的にチェックできないため、コンパイラーは警告を発行します。ただし、データ構造のセマンティクスがわかっている場合は、警告を抑制できます。

_    @SuppressWarnings("unchecked")
    T resultT = (T)result;
_

PS:ワイルドカードキャプチャーは必要ありません。以下の場合はまったく同じように機能します。

_    private HashMap<Class<?>, HashMap<Entity, Component>> m_componentStores;
_
4
rustyx