yapkm01
yapkm01

Reputation: 3761

Generic method bounded type parameter and type erasure

A generic method as per below:

static <E, K extends E> void someMethod(K k, E[] e) {}

I presumed upon erasure, the erasure type would be:

static void someMethod(Object k, Object[] e) {}

Just curious how would the type parameter knows the constraints after type erasure? That type parameter K is bounded to E?

Upvotes: 4

Views: 2165

Answers (3)

newacct
newacct

Reputation: 122499

I want to note that, in fact, your type constraint

static <E, K extends E> void someMethod(K k, E[] e) {}

has exactly the same effect (at compile time) as

static void someMethod(Object k, Object[] e) {}

Try calling someMethod("foo", new Integer[3]) if you don't believe me.

This is because it is valid for the compiler to infer Object as the parameters for both E and K (since any K object is also an instance of Object, and any E[] object is also an instance of Object[] (remember that array types are covariant in Java)).

This is a common pitfall in Java Generics. For example, the Arrays.fill() method has the signature static void fill(Object[] a, Object val); it is not possible for them to restrict it further.

Upvotes: 2

Joshua Kaplan
Joshua Kaplan

Reputation: 883

Your type-erased signature is correct. However, the constraints of a method are not erased during compilation. They are encoded in metadata that is used at compile time (and not normally used at runtime although it can be accessed via reflection*). For example the class java.util.ArrayList<E> has the method:

public E get(int index)

Which with type-erasure becomes:

public Object get(int index)

However, in your code if you parameterize ArrayList with String then you will be to call the get(...) method without need to cast the result to a String despite the type-erasure.

This is different from what happens when you parameterize a class or method call. The provided parameterizations are completely erased at compile time. For example:

ArrayList<String> myList = new ArrayList<String>();

After compilation is equivalent to:

ArrayList myList = new ArrayList();

*Accessing this information at run time via reflection can be done by using reflection methods which return java.lang.reflect.Type instances. For example, to get the constraints of your method at runtime you could call java.lang.reflect.Method's getGenericParameterTypes() method. Processing this returned information would make it possible to determine the constraints at run time.

Upvotes: 2

Bohemian
Bohemian

Reputation: 425288

You are correct about the erasure. Actually, the runtime doesn't know about the constraints. Only the compiler does.

Upvotes: 8

Related Questions