3

我正在阅读 Oracle 上的泛型跟踪(Type Erasure),但我无法理解以下部分。

代码片段如下所示:

public class Node<T> {

    public T data;

    public Node(T data) { this.data = data; }

    public void setData(T data) {
        System.out.println("Node.setData");
        this.data = data;
    }
}

public class MyNode extends Node<Integer> {
    public MyNode(Integer data) { super(data); }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }
}

该线索提到以下内容:

考虑以下代码:

MyNode mn = new MyNode(5);
Node n = mn;            // A raw type - compiler throws an unchecked warning
n.setData("Hello");     
Integer x = mn.data;    // Causes a ClassCastException to be thrown.

类型擦除后,此代码变为:

MyNode mn = new MyNode(5);
Node n = (MyNode)mn;         // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = (String)mn.data; // Causes a ClassCastException to be thrown.

引用同一个教程 -

这是执行代码时发生的情况

  • n.setData("你好"); 导致方法 setData(Object) 在 MyNode 类的对象上执行。(MyNode 类从 Node 继承了 setData(Object)。)
  • 在 setData(Object) 的主体中,将 n 引用的对象的数据字段分配给一个 String。
  • 通过 mn 引用的同一对象的数据字段可以被访问,并且应该是一个整数(因为 mn 是一个 MyNode,它是一个 Node.js。
  • 尝试将 String 分配给 Integer 会导致 Java 编译器在分配时插入的强制转换引发 ClassCastException。

我无法理解为什么尝试检索数据会导致异常。据我了解,不应该设置数据本身引发异常(这是我的编译器发生的情况,但由于我没有使用 Oracle 的编译器,我不确定哪个是正确的)?

如果我的理解是正确的,那么 MyNode 类应该有两种方法:

void setData(Object); //bridge method
void setData(Integer);

因此,在 Node 上调用 setData(Object) 应该正确地调用 MyNode 中的 bridge 方法,该方法又调用 setData(Integer) ,这是应该抛出类转换异常的地方。但是甲骨文的教程特意说事实并非如此。那么我的理解有什么问题呢?请帮我理解。

4

2 回答 2

0

如果我的理解是正确的,那么 MyNode 类应该有两个方法
void setData(Object); //桥接方法
void setData(Integer);

那是真实的。MyNode 类将具有以上两种方法。

做一个javaponMyNode.class也可以揭示它。请参阅以下在 ** 之间突出显示的两种方法

javap MyNode.class
Compiled from "MyNode.java"  
public class com.demo.generics.demo.MyNode extends com.demo.generics.demo.Node<j
ava.lang.Integer> {
  public com.demo.generics.demo.MyNode(java.lang.Integer);
  **public void setData(java.lang.Integer);**
  public static void main(java.lang.String[]);
  **public void setData(java.lang.Object);**
}

因此,在 Node 上调用 setData(Object) 应该正确地调用 MyNode 中的 bridge 方法,该方法又调用 setData(Integer) ,这是应该抛出类转换异常的地方。

这也是真的。调用它会导致以下异常:

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at com.demo.generics.demo.MyNode.setData(MyNode.java:1)
    at com.demo.generics.demo.MyNode.main(MyNode.java:14)

MyNode.java:14是我打电话的地方n.setData("Hello");

这就是我的编译器发生的情况,但由于我没有使用 Oracle 的编译器,我不确定哪个是正确的)?

这不依赖于编译器,它应该是相同的。

于 2016-03-13T12:30:33.423 回答
0

我昨天在阅读文档时遇到了这个问题。我在 Oracle 错误跟踪器中打开了这个错误,并添加了这个问题作为参考。

于 2019-06-21T09:55:31.860 回答