4

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?

Bohemian
  • 365,064
  • 84
  • 522
  • 658
yapkm01
  • 2,905
  • 6
  • 34
  • 52

3 Answers3

8

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

Bohemian
  • 365,064
  • 84
  • 522
  • 658
2

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.

Joshua Kaplan
  • 658
  • 4
  • 5
2

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.

newacct
  • 110,405
  • 27
  • 152
  • 217