简体   繁体   中英

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. 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. You can get the details of type erasure nicely in this tutorial 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.

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.

The LIST no longer knows what its generics param is at runtime. 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. There's no .getComponentType() method or any such.

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.

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 . 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.

Every object knows its own type at runtime (accessible through 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> ; it just has two List s. This can be demonstrated by the fact that new ArrayList<Integer>().getClass() == new ArrayList<String>().getClass() evaluates to true.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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