First code example
The first code example has a compilation error. You can test it yourself in your IDE.
Mine says: The method add(N) in the type List<N> is not applicable for the arguments (Node<N>)
The problem is that N is a subtype of Node. List N can be a StupidNode list, where StupidNode is a subclass of Node. But the current instance may not be a StupidNode, it may be a different subclass of Node, so adding it may be wrong .
Second code example
Now the second code example is one where a developer who is annoyed by a compile-time error that he does not understand, believes that the compiler is wrong and is trying to force the cast. Such a listing does compilation of the code, but can break at runtime under the same conditions (as explained above).
Therefore, the compiler issues a warning to help you understand that something may be wrong.
Sample problem
For previous code samples, a problem may arise if the call code is written (for two subclasses of NodeA and NodeB of Node ):
Node<NodeA> root = new NodeA<NodeA>(null);
In the second line, the code that will be run in the Node constructor will be interpreted as (replacing the N format parameter with the current NodeB parameter):
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);
As you can see, the second line of the caller will pass the NodeA instance, while the Node constructor expects a NodeB ! Hence the error ...
UPDATE , as the comment asked: sample code for subclasses of NodeA (or NodeB).
public class NodeA extends Node<NodeA> { public NodeA(NodeA parent) { super(parent); } }