Java泛型类型擦除:字段上的运行时类型检查

Java泛型类型擦除:字段上的运行时类型检查,java,Java,我正在学习关于泛型的Java教程,并以自己的方式在上玩示例 两类: public class Node<T> { private T data; public Node(T data) { this.data = data; } public void setData(T data) { this.data = data; } } public class MyNode extends Node<In

我正在学习关于泛型的Java教程,并以自己的方式在上玩示例

两类:

public class Node<T> {
    private T data;
    public Node(T data) { 
        this.data = data; 
    }
    public void setData(T data) {
        this.data = data;
    }
}

public class MyNode extends Node<Integer> {
    public MyNode(Integer data) { 
        super(data); 
    }
    public void setData(Integer data) {
        super.setData(data);
    }
}
因为第3行实际上调用的是类型擦除方法Node.setData(Object)。但是将抛出运行时
ClassCastException

这是我的实验:我打印出字段
数据的类型。它在Node和MyNode中都是
对象

以下是我的问题:

  • 节点有一个
    对象
    类型,由于类型擦除,这并不奇怪。但是为什么MyNode也有一个“数据”的
    对象
    类型呢

  • 如果MyNode的“数据”具有
    对象
    类型,那么运行时类型检查是如何工作的?(ClassCastException
  • exception…)在我看来,MyNode中的数据类型也被删除了(我的谜题#1)


    Java版本:HotSpot 1.8.0_05-b13

    这与
    泛型
    类型擦除无关

    您正在告诉编译器
    节点n
    ,但没有提供任何类型,因此它将接受任何内容

    这与将
    ArrayList
    下放到
    List
    并抱怨它需要任何东西没有什么不同

    final List los=new ArrayList();
    新增服务水平(新日期());
    增加(1);
    
    这是一个定义良好的预期行为,它是按照你的要求去做的


    除了确切地告诉它做什么,你还期望它做什么?这与
    泛型
    类型擦除
    无关

    您正在告诉编译器
    节点n
    ,但没有提供任何类型,因此它将接受任何内容

    这与将
    ArrayList
    下放到
    List
    并抱怨它需要任何东西没有什么不同

    final List los=new ArrayList();
    新增服务水平(新日期());
    增加(1);
    
    这是一个定义良好的预期行为,它是按照你的要求去做的

    除了确切地告诉它做什么,你还期望它做什么? 我打印出了字段数据的类型

    您可能打印出来的是一个名为“data”的引用类型。它确实设置为
    对象

    但是为什么MyNode也有“数据”的对象类型呢

    不确定你在谈论哪些数据。局部变量
    数据
    的引用类型将是
    整数
    ,而属性引用类型是
    对象

    如果MyNode的“数据”具有对象类型,那么运行时类型检查是如何工作的?(ClassCastException异常…)在我看来,MyNode中的数据类型也被删除了(我的谜题#1)

    执行此操作时:

    public void setData(Integer data) {
            super.setData(data);
    }
    
    Java编译器将其转换为:

    public void setData(Object arg) {
       Integer data = (Integer) arg;
        //Now you can use "data" refenrence with proper type
       super.setData(data);
    }
    
    这就是ClassCastException的来源

    我打印出了字段数据的类型

    您可能打印出来的是一个名为“data”的引用类型。它确实设置为
    对象

    但是为什么MyNode也有“数据”的对象类型呢

    不确定你在谈论哪些数据。局部变量
    数据
    的引用类型将是
    整数
    ,而属性引用类型是
    对象

    如果MyNode的“数据”具有对象类型,那么运行时类型检查是如何工作的?(ClassCastException异常…)在我看来,MyNode中的数据类型也被删除了(我的谜题#1)

    执行此操作时:

    public void setData(Integer data) {
            super.setData(data);
    }
    
    Java编译器将其转换为:

    public void setData(Object arg) {
       Integer data = (Integer) arg;
        //Now you can use "data" refenrence with proper type
       super.setData(data);
    }
    

    这就是ClassCastException的来源。

    为什么要覆盖
    setData
    方法。因为您继承了它,所以不需要重新实现它。覆盖正是测试的重点。它说明了这个问题。为什么要覆盖
    setData
    方法。因为您继承了它,所以不需要重新实现它。覆盖正是测试的重点。这说明了问题所在,这是一个很好的观点。引用类型在这里没有任何意义,因为编译器重写
    setData(Object)
    。我已经运行了一个
    javap-c
    来确认它。谢谢,这是一个很好的观点。引用类型在这里没有任何意义,因为编译器重写
    setData(Object)
    。我已经运行了一个
    javap-c
    来确认它。谢谢,你误解了我的问题。我一点也不惊讶于这种类型的删除。我实际上是在为我的实验制造问题。我问的是运行时类型检查。请查看另一个答案。这与擦除无关,与以下事实有关:
    节点n
    上没有类型信息,没有“擦除”内容,它是
    对象
    如果没有其他内容,请再次检查问题帖子和所选答案。这个问题与节点无关。你误解了我的问题。我一点也不惊讶于这种类型的删除。我实际上是在为我的实验制造问题。我问的是运行时类型检查。请查看另一个答案。这与擦除无关,与以下事实有关:
    节点n
    上没有类型信息,没有“擦除”内容,它是
    对象
    如果没有其他内容,请再次检查问题帖子和所选答案。这个问题与
    节点
    无关。