Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Java, why is there no generic type info at run time?

Tags:

java

generics

Consider this example taken from a book, with a super class Gen and a subclass Gen2...

class Gen<T> { }

class Gen2<T> extends Gen<T> { }

Now the book states following will not compile (lets assume its in a main method)

Gen2<Integer> obj = new Gen2<Integer>();

if (obj instanceof Gen2<Integer>) {

    //do something
}

This can't be compiled because generic type info does not exist at runtime. If it doesn't exist at runtime, when does it exist? I thought that it would not exist at compile time, but would exist at runtime. Certainly, the following works for runtime with a wildcard...

if (obj instanceof Gen<?>) {

    //do something else

}

So to clarify, my question is why does generic type info not exist at runtime? Have I overlooked a simple concept?

like image 824
Rob L Avatar asked Mar 17 '14 23:03

Rob L


People also ask

Is generic type information present at runtime?

Generic type information is not present at runtime. C. You cannot create an instance using a generic class type parameter.

Are generics applied at compile time or run time?

In order to use a generic class, you have to give it a type parameter at compile time, but the type parameter could be of an interface or base class, so the actual, concrete type of the objects used at runtime can vary.

What happens at compile time with generic types?

Generics are checked at compile-time for type-correctness. The generic type information is then removed in a process called type erasure. For example, List<Integer> will be converted to the non-generic type List , which ordinarily contains arbitrary objects.


2 Answers

The problem is that generics was not always present in java (I think they added it in 1.5). So in order to be able to achieve backwards compatibility there is type erasure which effectively erases generic type information while compiling your code in order to achieve that goal.

Excerpt from the relevant parts of the official documentation:

During the type erasure process, the Java compiler erases all type parameters and replaces each with its first bound if the type parameter is bounded, or Object if the type parameter is unbounded.

So this code for example

public class Node<T extends Comparable<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; }
    // ...
}

becomes this after type erasure:

public class Node {

    private Comparable data;
    private Node next;

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

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

There is a way however to resurrect some of that type information if you tread the path of reflection which is like a lightsaber: powerful but also dangerous.

like image 136
Adam Arold Avatar answered Sep 21 '22 19:09

Adam Arold


You have "overlooked a simple concept". The generics exist only at compile time, and only to enforce things like parametric polymorphism. Because the folks who implemented them decided that developers should be able to use them (generics) and still deploy their built artifacts to targets with older JVMs (an extremely questionable decision in my mind, as the runtime libraries also changed between 1.4 and 1.5), they had the compiler decide if everything type-checks and then they throw away almost all of that information before creating the compiled artifact.

I say almost all of that information because in some special cases it is still around at runtime.

like image 20
Judge Mental Avatar answered Sep 23 '22 19:09

Judge Mental