Java 泛型 GetThis 技巧说明

发布于 2024-08-15 12:36:02 字数 1263 浏览 4 评论 0原文

我正在阅读有关 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 s 是最好的 避免。

有人能给我一个上面代码抛出 ClassCastException 的例子吗?

谢谢。

I am reading about Java Generics and I came across this topic where I am a bit confused.

From : 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);
   }
} 

Scrolling lower a couple of screens...

public abstract class Node <N extends Node<N>>  {
   ...
   protected Node(N parent) {
     this.parent = parent;
     parent.children.add( (N)this ); // warning: unchecked cast
   }
   ...
 }

Casts whose target type is a type
parameter cannot be verified at
runtime and lead to an unchecked
warning. This unsafe cast introduces
the potential for unexpected
ClassCastException s and is best
avoided.

Could someone give me an example where the above code throws a ClassCastException ?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

独夜无伴 2024-08-22 12:36:02

第一个代码示例

在第一个代码示例中,存在编译错误。您可以在 IDE 中自行验证。

我的说:List类型中的方法 add(N) 是不适用于参数 (Node)

问题是 N 是 Node 的子类型。 N 的列表可能是 StupidNode 的列表,其中 StupidNode 是 Node 的子类。但当前实例可能不是 StupidNode,它可能是 Node 的不同子类,因此添加它可能是错误的


第二个代码示例

现在,在第二个代码示例中,开发人员对他不理解的编译时错误感到恼火,认为编译器是错误的并尝试强制转换。
这样的转换使代码可以编译,但可能在相同条件下在运行时中断(如上文所述)。

因此,编译器会发出警告,帮助您了解可能出现错误。


示例问题

调用代码写入(对于 Node 的两个子类 NodeANodeB),则可能会出现问题:

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 的构造函数中运行的代码将被解释为(用当前参数 NodeB 替换格式参数 N) :

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);
   }
}

First code sample

In the first code sample, there is a compile-error. You can verify 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. The List of N might be a list of StupidNode, where StupidNode is a subclass of Node. But the current instance might not be a StupidNode, it could be a different subclass of Node, so adding it could be wrong.


Second code sample

Now the second code sample is one where the developer, annoyed by the compile-time error that he doesn't understand, believes the compiler is wrong and try to force a cast.
Such a cast make the code compile, but could break at runtime in the same conditions (as explained higher).

Therefore, the compiler issues a warning, to help you understand that something could be wrong.


Sample problem

For both previous code samples, the problem could happen if the calling code writes (for two subclasses NodeA and NodeB of Node):

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);

On the second line, the code that will run in the constructor of Node will interpret like (replacing the format parameter N by the current parameter 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
   }
  // ...
 }

As you can see, the second line of the caller will pass a NodeA instance, while the constructor of Node expects a NodeB! Hence the error...


UPDATE as asked by comment : sample code for subclasses NodeA (or NodeB).

public class NodeA extends Node<NodeA>  {
   public NodeA(NodeA parent) {
     super(parent);
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文