我正在阅读有关Java泛型的文章,遇到了这个话题,我对此感到有些困惑。

来自:http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ205

public abstract class Node <N extends Node<N>>  {
   private final List<N> children = new ArrayList<N>();
   private final N parent;

   protected Node(N parent) {
     this.parent = parent;
     parent.children.add(this);  // error: incompatible types
   }
   public N getParent() {
     return parent;
   }
   public List<N> getChildren() {
     return children;
   }
 }

public class SpecialNode extends Node<SpecialNode> {
   public SpecialNode(SpecialNode parent) {
     super(parent);
   }
}

向下滚动几个屏幕...
public abstract class Node <N extends Node<N>>  {
   ...
   protected Node(N parent) {
     this.parent = parent;
     parent.children.add( (N)this ); // warning: unchecked cast
   }
   ...
 }



有人可以举一个上面的代码抛出ClassCastException的例子吗?

谢谢。

最佳答案

第一个代码样本
在第一个代码示例中,有一个编译错误。您可以在IDE中自己进行验证。
我的说:The method add(N) in the type List<N> is not applicable for the arguments (Node<N>)问题在于N是Node的子类型。 N的列表可能是StupidNode的列表,其中StupidNode是Node的子类。但是当前实例可能不是StupidNode,它可能是Node的另一个子类,因此添加它可能是错误的

第二个代码样本
现在,第二个代码示例是一个示例,在该示例中,开发人员由于不理解他的编译时错误而感到恼火,他认为编译器是错误的,并试图强制进行强制转换。
这样的转换可以编译代码,但是可以在相同的条件下(如上所述)在运行时中断。
因此,编译器会发出警告,以帮助您理解某些错误。

样本问题
对于前面的两个代码示例,如果调用代码写入(对于NodeA的两个子类NodeBNode),则可能会发生此问题:

Node<NodeA> root = new NodeA<NodeA>(null);
// code needs a change, to be able to handle the root, that has no parent
// The line with parent.children will crash with a NullPointerException
Node<NodeB> child = new NodeB<NodeB>(root);
在第二行中,将在Node的构造函数中运行的代码将解释为(将格式参数N替换为当前参数NodeB):
public abstract class Node <NodeB>  {
   private final List<NodeB> children = new ArrayList<NodeB>();
   private final NodeB parent;

   protected Node(NodeB parent) {
     this.parent = parent;
     parent.children.add(this);  // error: incompatible types
   }
  // ...
 }
如您所见,调用者的第二行将传递一个NodeA实例,而Node的构造函数则期望一个NodeB!因此,错误...

根据注释要求更新:子类NodeA(或NodeB)的示例代码。
public class NodeA extends Node<NodeA>  {
   public NodeA(NodeA parent) {
     super(parent);
   }
}

09-25 20:59