我怎样才能贬低到class级’E型或至少在没有警告的情况下安全地进行?

我有超级抽象类Node和50种子类SubNode。

我有一个通用的Class ,它有一个私有var List 和一个方法,不幸的是它必须接受超类Node ALWAYS,不能将它移动到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; } 

任何解决方案(Reflection?)能够在没有警告的情况下编译,抛出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 } 

如果你被迫以某种方式拥有一个

 public void addSubElement (Node node); 

那么你唯一的选择就是使用

 public void addSubElement (Node node){ subElements.add((E)node); } 

如果没有得到警告(你当然可以压制),就没有办法实现这一点。

这是好的,只要你是唯一一个使用这种方法的人,你可以忽略警告,只要你确保总是用正确的参数调用它。

你的设计有缺陷。 方法的签名应该是:

 public void addSubElement (E node) 

subElements应为List类型而不是List

假设您的类是NodeList ,然后您创建一个实例:

 NodeList nl = new NodeList(); 

然后列表将只接受SubNode1实例,因此您将无法做到

 nl.addSubElement(subNode2Instance) 

更新:

我找到的唯一解决方法是:

 private static class G { private E templateObject; private List subElements = new ArrayList(); 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(); } } } 

使用generics时,有些情况下您无法在不抑制警告的情况下编写有效代码。

针对您的问题的纯OO方法是为每种类型编写addSubElement()方法。 这将为每种类型(N * N)提供每种类型一种方法。 您可以在相应类型中添加特殊情况。

显然,对于任何大量不同类型(比如说超过三种),方法的数量会迅速爆炸,你会发现自己处于需要剪切和粘贴大量代码的情况。

即使您只需要编写其中的一些并将大部分工作委托给通用的addSubElement(Node)方法,它仍然会产生技术债务,因为您需要为每种新类型编写X方法。

因此,对于你的角落案例,可能无法绕过instanceof@SuppressWarnings("unchecked")

[编辑]

您可以定义Node必须实现的接口INode 。 你的课程可能如下所示:

 public Node { @SuppressWarnings("unchecked") public void addSubElement(N n) { ... } } 

此模式允许您限制此实现接受的节点的可能类型,或者使用Node for N来接受任何内容以及在方法中进行特殊处理的内容。

这里的优点是,当您将类型传递给无法处理它的实现时,您可能会遇到编译时错误。 但是你仍然需要在方法中使用强制转换来抑制警告。

编辑:所有其他答复的最终答案:

如果接受titofb回答,我会犹豫不决,因为他是指定好方法的人。 但是我觉得这个问题足以针对我自己的问题(第一次),为了阅读它的其他人的利益。 谢谢大家!

抽象Node类实现了这个:

  @SuppressWarnings("unchecked") protected final Class getChildType(){ return (Class)(((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]); } 

所以任何Subnode总是有一个可用的方法,它从定义中返回自己的Type E SubnodeN扩展Node (Node 中的SubnodeX = N)。 这意味着我们可以在任何节点中执行此操作:

  public void addSubElement (Node node){ Class 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 }