私は次のコードを持っています:
_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
_
この警告が表示されないようにするには何が欠けていますか?
Class.cast
はあなたが欲しいものです。さて、あなたは反射を使用しないことを検討するかもしれません。
行を変更します。
T result = (T)store.get(e);
に:
T result = exampleClass.cast(store.get(e));
Castステートメントの上に@SuppressWarnings("unchecked")
を記述します。
@SuppressWarnings("unchecked")
T result = (T)store.get(e);
警告を無視しても安全である理由を説明する説明を追加します。
ジェネリックのextends
は、実際にはそのようには機能しません。 T
!= _? extends Component
_であっても_T extends Component
_。あなたが持っているものは実際には ワイルドカードキャプチャ であり、それは別の目的を持っています。
そして、はい、あなたのソリューションはタイプセーフではありません-以下の2つの_?
_マークの間に関係はありません:
_ private HashMap<Class<?>, HashMap<Entity, ? extends Component>> m_componentStores;
_
そのため、キーとしてComponent
のサブクラスのインスタンスをこの構造体に配置することは、他のクラス(Component
のサブクラスでさえも)を使用することもできます。
ジェネリック型はコンパイル時でのみ解決されるため、実行時_m_componentStores
_には、extends
Component
以外に、そこにある値の正確なタイプを知る方法がありません。
したがって、store.get(e)
から取得する型は... Component
です。
_ Component result = store.get(e);
_
Component
をT
にキャストすると、キャストを静的にチェックできないため、コンパイラーは警告を発行します。ただし、データ構造のセマンティクスがわかっている場合は、警告を抑制できます。
_ @SuppressWarnings("unchecked")
T resultT = (T)result;
_
PS:ワイルドカードキャプチャーは必要ありません。以下の場合はまったく同じように機能します。
_ private HashMap<Class<?>, HashMap<Entity, Component>> m_componentStores;
_