我有超级抽象类节点和50种亚类子节点。
我有一个泛型类<E扩展节点>其中有一个私人变种名单<E>和不幸有始终接受父节点的方法,不能移动它只是E:
public void addSubElement (Node node){
if (node instanceOf E) subElements.add((E)node);
else //Doing extra steps for occasional non-E nodes like discarding them silently without CastException;
}
任何解决方案(反射?)能编译没有警告,扔CastException,而不是添加任何对象,由于类型擦除?? ...
我不希望有写相同功能的任何类型的子类:
public void addSubElement (Node node){
if (node instanceOf SubNode1) subElements.add((SubNode1)node);
if (node instanceOf SubNode2) subElements.add((SubNode2)node);
//if (node instanceOf SubNode50....
}
这将是这么好的有喜欢的方法。
public void addSubElement (Node node){
subElements.add((E)node.autoCastToSubClassOfAbstract("Node")); //Should throw CastException if non-E
}
要么
public void addSubElement (Node node){
subElements.add(node.autoCastTo("E")); //Should throw CastException if non-E
}
Answer 1:
如果你以某种方式被迫有
public void addSubElement (Node node);
那么你唯一的选择是使用
public void addSubElement (Node node){
subElements.add((E)node);
}
有没有办法实现这一目标没有得到一个警告(你当然可以抑制)。
这是罚款,只要你使用这种方法只有一个,你可以忽略这个警告,只要你确保始终以正确的参数调用它。
Answer 2:
你在你的设计中的缺陷。 无论是方法的签名应该是:
public void addSubElement (E node)
或subElements
应该是类型的List<Node>
代替List<E>
比方说,你的类是NodeList<E extends Node>
,然后创建一个实例:
NodeList<SubNode1> nl = new NodeList<SubNode1>();
然后,该列表将只接受的情况下SubNode1
,这样你就不会能够做到
nl.addSubElement(subNode2Instance)
更新:
我发现的唯一的解决方法是这样的:
private static class G<E extends NodeB> {
private E templateObject;
private List<E> subElements = new ArrayList<E>();
public G(E templateObject) {
this.templateObject = templateObject;
}
public void addSubElement (NodeB node) {
if (templateObject.getClass().isAssignableFrom(node.getClass())) {
subElements.add((E) node);
} else {
throw new ClassCastException();
}
}
}
Answer 3:
当使用泛型,还有角落情况下,你不能没有抑制警告编写有效的代码。
有关问题的纯面向对象的方法是在写addSubElement()
为每种类型的方法。 这将使你每一个类型的方法在每个类型(N * N)。 你可以在相应类型添加特殊情况。
显然,对于不同类型的任何显著号(说三个以上),方法的数量迅速爆炸,你会发现自己在那里你必须复制粘贴大量的代码的情况。
即使你只需要编写一些他们并委托大部分工作提高到一个通用的addSubElement(Node)
的方法,但它仍然会造成技术的债务,因为你需要写为每个新的X型的方法。
因此,对于你的角落的情况下,有可能是周围也没有路instanceof
和@SuppressWarnings("unchecked")
[编辑]
你可以定义一个接口INode
,其Node
必须实现。 然后,您的类可以是这样的:
public Node<E,N extends INode> {
@SuppressWarnings("unchecked")
public void addSubElement(N n) { ... }
}
这种模式将让您无论是限制可能的类型此实现接受节点或使用Node
的N
的东西,接受任何东西,在那里你在做的方法进行特殊处理。
这里的好处是,你可以得到,当你传递一个类型,它不能处理它的实现编译时错误。 但是,你仍然需要在方法铸造并抑制警告。
Answer 4:
编辑:最后的答案与所有其他解答:
,我当时犹豫是否接受titofb答案beause他是谁任命的好办法之一。 但我认为这是不够的目标上应该aceptŸ问题我自己(非常1次),为他人谁读它的好处。 谢谢大家!
抽象节点类实现这一点:
@SuppressWarnings("unchecked")
protected final Class<E> getChildType(){
return (Class<E>)(((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
因此,任何具有子节点总是从定义SubnodeN返回自己的E型可用的方法扩展节点<SubNodeX>(SubnodeX = N在节点<E>)。 这意味着,我们可以做到在任何节点:
public void addSubElement (Node<?> node){
Class<E> expectedChildType = getChildType();
if (expectedChildType.isAssignableFrom(node.getClass())){//if node instanceOf E
subElements.add(expectedChildType.cast(node));
}
else throw new ClassCastException("A non-expected child was intended to add to this "+this.getClass().getSimpleName()+" element");
}
然后这里是神奇的。 这是默认的行为。 它警告你,如果一些孩子没有预料到的,但是你可以重写此方法对于任何子节点处理特殊情况:
@Override
public void addSubElement (Node<?> node){
if (node instanceOf SubNode34) {/* Yes, our current subnode does not expect all elements intended to be added as E type nodes, we can silently discard or do whatever */}
else super.addSubElement(node) //Parents default behavior
}
文章来源: How can I downcast to class' type E or at least make it in a safe way without warnings?