我有以下代码:
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
我错过了什么来防止出现此警告?
答案 0 :(得分:37)
Class.cast
就是你想要的。好吧,你可能会考虑不使用反射。
更改行:
T result = (T)store.get(e);
为:
T result = exampleClass.cast(store.get(e));
答案 1 :(得分:16)
在Cast语句上方写@SuppressWarnings("unchecked")
:
@SuppressWarnings("unchecked")
T result = (T)store.get(e);
并添加一个解释性声明,说明为什么忽略警告是安全的。
答案 2 :(得分:4)
extends
并不是真的那样。 T
!= ? extends Component
即使是T extends Component
。你所拥有的实际上是wildcard capture,它有不同的目的。
是的,您的解决方案不是类型安全的 - 以下两个?
标记之间没有关系:
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;