简体   繁体   English

Java运行时在运行时执行类型擦除时如何知道泛型

[英]How does java runtime knows the generic type when it perform type erasure at run time

Consider the following code. 考虑下面的代码。

    List<Animal> x = new ArrayList<>();

    x.add(new Tiger());

    for(Animal d : x) {
        System.out.println(d.getClass());
    }

The above prints out 上面打印出来

Tiger

Another example is 另一个例子是

public static  <E> void containsElement(E [] elements, E element){
    for (E e : elements){
        System.out.println(e.getClass());
    }
}

Always prints out the correct class 始终打印正确的班级

If I recall correctly, java cannot find the generic type at run time because it performs type erasure. 如果我没记错的话,java在运行时找不到通用类型,因为它执行类型擦除。 Am I setting this up wrong? 我设置错了吗?

In runtime, you will always get correct class. 在运行时,您将始终获得正确的类。 Type erasure happens during the compilation time when compiler generates the byte code. 类型擦除发生在编译器生成字节码时的编译期间。 When the type is unbounded, compiler replaces with Object and when its bounded, it replaces with the higher bound. 当类型为无界时,编译器将替换为Object,而当其为有界时,则将其替换为更高的界限。 You can get the details of type erasure nicely in this tutorial https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html 您可以在本教程https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html中很好地获得类型擦除的详细信息。

The List has type erasure, but the Object's class doesn't have anything to do with Java Generics and type erasure. 列表具有类型擦除,但是对象的类与Java泛型和类型擦除没有任何关系。

The same would happen without using generics at all. 如果根本不使用泛型,则会发生相同的情况。

For example: 例如:

Animal a = new Tiger(); 
System.out.println(a.getClass()); 

would also print out Tiger. 也会打印出Tiger。

The LIST no longer knows what its generics param is at runtime. LIST不再知道其运行时的泛型参数是什么。 In other words, if I hand 'x' to a method, you can tell that it is a List (for example, x.getClass() would give you something listy, and x instanceof List would be true ), but there is no way to tell that it is a list of Animals. 换句话说,如果我将“ x”传递给方法,则可以说它是一个列表(例如, x.getClass()会给您带来些刺激的感觉,而x instanceof List将是true ),但是没有告诉它是动物列表的方法。 There's no .getComponentType() method or any such. 没有.getComponentType()方法或任何此类方法。

The objects inside the list know they are animals, so, once you get one object out (which the for loop you wrote in your code does), you can ask the object what it is. 列表中的对象知道它们是动物,因此,一旦取出一个对象(在代码中编写的for循环即可),就可以询问该对象是什么。

Imagine that list had nothing in it, for example. 例如,假设该列表中没有任何内容。 No way to tell. 没办法说。 Consider also, this: 还考虑一下:

List<Number> numbers = new ArrayList<Number>();
List<Integer> integers = new ArrayList<Integer>();
numbers.add(Integer.valueOf(1));
integers.add(Integer.valueOf(1));

From here, you can ask for the first element in either list and it'll be of type java.lang.Integer . 在这里,您可以要求任一列表中的第一个元素,其类型为java.lang.Integer But there's no way to know that the list numbers was defined to take any Number (Integer is a subtype of Number), and integers was defined to take only integers. 但是无法知道列表numbers被定义为可以接受任何Number(Integer是Number的子类型),而integers被定义为仅可以接受整数。

Every object knows its own type at runtime (accessible through getClass() ). 每个对象在运行时都知道自己的类型(可通过getClass()访问)。 Type erasure is where generic types (ie List<T> ) "forget" what type they have at runtime, which means that the JVM can't tell the difference between a List<Integer> and a List<String> ; 类型擦除是泛型类型(即List<T> )在运行时“忘记”它们具有什么类型的地方,这意味着JVM无法分辨List<Integer>List<String>之间的区别; it just has two List s. 它只有两个List This can be demonstrated by the fact that new ArrayList<Integer>().getClass() == new ArrayList<String>().getClass() evaluates to true. new ArrayList<Integer>().getClass() == new ArrayList<String>().getClass()评估为true可以证明这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM