通过java中的擦除类型参数化是什么意思?

时间:2015-03-13 15:34:58

标签: java arrays generics jvm bytecode

在阅读关于JVM时..我遇到了这些行

  

JVM对类型参数一无所知。所有类型参数都由Java编译器擦除   替换为Object类型。然后,参数类型T的数组变为上下文中的Object数组   JVM的原因,这就是为什么你不能写像新T [n]。

这样的表达式

这是否意味着当我写

  

功能(int a)

a被替换为类型对象,即使用整数对象? 或int[10]; 变为Integer[10]; 如果不是这样,它的意思是什么?

请用简单术语解释。

5 个答案:

答案 0 :(得分:3)

类型擦除仅指GenericsFunction(int a)等方法不会受到影响。

另一方面,此代码将:

public class Node<T> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) }
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}

将替换为:

public class Node {

    private Object data;
    private Node next;

    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }

    public Object getData() { return data; }
    // ...
}

(取自here

的例子

答案 1 :(得分:2)

  

所有类型参数都由Java编译器擦除,并替换为Object类型。

本段专门讨论泛型类中的类型参数。所以如果你写一个看起来像这样的方法

public <T> void foo(T arg);

生成的方法中arg的类型为java.lang.Object。非通用方法保持不变。

  

这是否意味着当我写function(int a)时a被类型对象替换,即使用整数对象?

不,它没有,因为该规则仅适用于泛型类的泛型方法和方法,这些泛型类使用泛型类型参数作为其参数或返回类型。

  

因此,如果我的List<>应该存储String,并且有关String的信息被删除并转换为Object,那么JVM如何知道它应该接受String 1}}存储在List<>中以及如何检查?

JVM不知道也不检查进入列表的对象类型,因为它没有相关信息。泛型类型参数的所有类型检查都在编译时完成。 JVM知道在运行时进入列表的对象实际上是String,因为编译器确保所有类型安全的代码路径都将字符串放入列表中。另一方面,你可以通过类型转换列表或使用它来欺骗编译器让你将无效对象放入列表(例如,Integer s到String列表中)。非泛型方法,但愚弄编译器需要您采取慎重行动。

有关类型删除的详细信息,请参阅this tutorial

答案 2 :(得分:1)

你弄错了:类型擦除与Java Generics有关。

如果您编写类似List<String> l = new ArrayList<String>();的内容,则在编译过程中会删除有关String的信息; JVM对此一无所知。

答案 3 :(得分:0)

没有。类型参数是尖括号中的东西。

List<Integer> list = new List<>();

Integer是类型参数。

答案 4 :(得分:0)

类型擦除适用于泛型的使用。在类文件中肯定有元数据来说明方法/类型是否是通用的,以及约束是什么等等。但是当使用泛型时,它们被转换为编译时检查和执行时转换。