2

关于类型擦除的 Java教程似乎没有详细说明编译器强制转换插入的具体规则。有人可以解释导致教程详述的转换的具体规则(转载如下):

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 = (MyNode)mn;         // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = (String)mn.data; // Causes a ClassCastException to be thrown.

具体来说,我想知道是什么规则导致了(MyNode)and的插入(String)。什么时候插入演员表,演员表的类型是如何选择的?

4

2 回答 2

3

ClassCastExceptionthrow当调用

n.setData("Hello");

这是因为编译器构建了桥接方法来保留多态性。桥接方法如下所示:

 public void setData(Object data) {
       setData((Integer)data);   //the exception is thrown here
  }

由于无法将字符串的实例转换为Integer,因此ClassCastException将抛出 。

您可以在此处阅读有关桥接方法的信息。

于 2015-06-01T08:03:58.327 回答
-1
  1. MyNode mn = new MyNode(5);

    • 将创建一个实例,该实例将接口MyNode的通用类型定义为TNodeInteger
    • 强制转换:开发人员不需要强制转换,编译器没有添加强制转换
  2. Node n = (MyNode)mn;

    • 这基本上会告诉编译器忘记泛型类型TNode完全使用没有泛型的接口,这将产生以下后果:想象泛型类型T被视为java.lang.Object
    • 强制转换:开发人员不需要强制转换,编译器没有添加强制转换
  3. n.setData("Hello");

    • 将允许您添加任何类型的 ob 对象,因为 T 被视为 Object ( String, Integer, array, 任何其他)
    • 强制转换:开发人员不需要强制转换,编译器没有添加强制转换
  4. Integer x = mn.data;

    • nm.data应该返回一个在IntegerInteger中定义为泛型类型参数TMyNode类型
    • 但是,因为您使用了允许您添加 a 的原始类型String,所以nm.data保存了一个String实例
    • 强制转换:开发人员不需要强制转换,但是编译器会在幕后为您添加转换到 Integer 并且由于类型不匹配,您将获得ClassCastException
于 2015-04-12T08:58:45.677 回答