Thursday, January 16, 2014

Java Type Erasure: Cannot perform instanceof check against parameterized type

Can we use something like this ?

public Object[] getElements(Object inputElement) {
if (inputElement instanceof List<Parameter>) {
return ((List<Parameter>) inputElement).toArray();
}
return new Object[] {};
}

No!!!!

Compiler Error message:
Cannot perform instanceof check against parameterized type List<Parameter>. Use the form List<?> instead since further generic type information will be erased at runtime


It's telling us to use List<?> more generic type rather than specific List<Parameter>.

public Object[] getElements(Object inputElement) {
if (inputElement instanceof List<?>) {
return ((List<?>) inputElement).toArray();
}
return new Object[] {};
}


Why?

In simple terms, generic types will be erased at compile time. 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.

It means, the .class file or generated byte code will not have any generic type information.


Below is the code after applying type erasure by compiler.

public Object[] getElements(Object inputElement) {
if (inputElement instanceof List) {
return ((List) inputElement).toArray();
}
return new Object[] {};
}


Other example from SUN docs:

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; }
    // ...
}

Because the type parameter T is unbounded, the Java compiler replaces it with Object:

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; }
    // ...
}


In the following example, the generic Node class uses a bounded type parameter:

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; }
    // ...
}
The Java compiler replaces the bounded type parameter T with the first bound class, Comparable:

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; }
    // ...
}


Resources:
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

No comments:

Post a Comment