有没有办法避免使用下面的@SuppressWarnings
并保持相同的功能而没有警告'类型安全:从AbstractDO []取消选中投射到E []':
public MyClass {
...
private Map<Class<? extends AbstractDO>, AbstractDO[]> map;
...
private void saveConcreteDOs(AbstractDO[] theEntities) {
entityMap.put(theEntities[0].getClass(), theEntities);
}
@SuppressWarnings("unchecked")
protected <E extends AbstractDO> E[] getConcreteDOs(Class<E> theType) {
return (E[]) map.get(theType);
}
...
}
也许增强地图声明?
答案 0 :(得分:3)
您可以选择:抑制您知道将永远成功的演员的警告,或者避免警告并通过try / catch块验证演员是否成功。
只有这两个选择。
也许有一种方法可以增强地图声明?
在你的情况下,我会说你有几个选择。
我认为您最好的选择是在throws ClassCastException
方法中添加getConcreteDOs
子句,并让调用者处理无效使用该方法所带来的无效演员 - 假设他们可以获得它围绕你的extends AbstractDO
条款进行编译。这会产生令人遗憾的副作用,即强制消费者将调用包装在try / catch块中,或者声明自己的throws子句以强制try / catch块在堆栈上方。
你可以用空的catch块吞下异常;坦率地说,我更喜欢@SuppressWarning。
或者您可以完全删除该方法,只处理抽象实体,有效地使您的存储库的使用者处理转换。
结论:每当您尝试构建通用存储库时,您都会遇到这些问题。使用具体的每个实体类型的存储库模式可能会更好。
答案 1 :(得分:1)
您可以通过使您的类具有通用性来避免未经检查的强制转换,例如
public class MyClass<E extends AbstractDO> {
private Map<Class<? extends AbstractDO>, E[]> map;
public void saveConcreteDOs(E[] theEntities) {
map.put(theEntities[0].getClass(), theEntities);
}
public E[] getConcreteDOs(Class<E> theType) {
return map.get(theType);
}
}
答案 2 :(得分:1)
首先,您的代码不是类型安全的。它可以在运行时抛出类转换异常。你应该
private void saveConcreteDOs(AbstractDO[] theEntities) { entityMap.put(theEntities.getClass().getComponentType(), theEntities); }
运行时可能只有齐次数组,而元素[0]的类型与数组组件类型相同。但是,通过单独考试这门课,没有办法知道这一点。
使用此更正的代码,超级智能编译器可以证明getConcreteDOs()
类型安全。然而javac并不那么聪明。语言规范要求发出警告。
通常,无法在Java中表达键和值之间更复杂的关系。不变量,即一个值是一个组件类型为键的数组,只保留在你的头脑中。
现在,看看这个非数组版本:
private Map<Class<? extends AbstractDO>, AbstractDO> map;
protected <E extends AbstractDO> E getConcreteDOs(Class<E> theType)
{
AbstractDO obj = map.get(theType);
return theType.cast(obj);
}
这没有任何警告,但它有点作弊。 Class.cast()
为我们隐藏警告,就是这样。
它对数组版本没有帮助,T[] castArray(Object[])
中没有Class<T>
。您可以自己制作一种方法,有效地隐藏其中的警告。
或者你可以做到这一点,但它实际上是不必要的俗气。如果你知道自己在做什么并且仔细检查了你的程序以确保类型安全,不要害怕未经检查的投射警告。
protected <E extends AbstractDO> E[] getConcreteDOs(Class<E[]> arrayType)
{
AbstractDO[] array = map.get(arrayType.getComponentType());
return arrayType.cast(array);
}
...
X[] array = getConcreteDOs(X[].class);