11

Java generics are implemented using type erasure. That means that if I have a method:

public void setMapParam(Map<String, Integer> p) { ... }

after compilation, it will end up in the .class as:

public void setMapParam(Map p) { ... }

I have a JAR file with generic classes and methods like the above. It is just the binary. No source code no nothing.

But when I use it in code, Eclipse auto completion gives me setMapParam(Map<String, Integer> p) even though in the binary is like setMapParam(Map p).

How does Eclipse now the type (Map<String, Integer>) even if the method signature has been type erased (to Map)? Or am I missing something?

ElenaT
  • 2,600
  • 4
  • 24
  • 41
  • Isn't type erasure at run time, not at compile time? I believe this is not an Eclipse thing but a Java thing, and the class and Jar files should have the generic information in them. – Hovercraft Full Of Eels Feb 20 '11 at 15:43
  • @Hovercraft Full Of Eels: Ok but if this info is in the class file it will be available at runtime when the class loader loads the class. So why type erasure in Java if the type information is in the class? I don't get it. What am I missing? – ElenaT Feb 20 '11 at 15:45
  • I believe that it's for the holy grail of backwards compatability. – Hovercraft Full Of Eels Feb 20 '11 at 15:46
  • A good answer was already given [here](http://stackoverflow.com/questions/937933/where-are-generic-types-stored-in-java-class-files) – skuro Feb 20 '11 at 16:03

2 Answers2

17

Type erasure does not mean that the compiled code contains no type parameter information. Type parameters that are used in class and member definitions are present in the compiled code and available via reflection (see TypeVariable).

What type erasure means is that object instances do not have individual type parameters. Given a class definition MapImpl extends HashMap<T extends Comparable, Integer> and an instance of that class, you cannot find out what specific value of T was used in the code that created the instance, because that information does not exist. But you can find out that it extends Comparable and that the value type is Integer, because that information is part of the class definition (and shared by all instances).

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • 1
    Good answer. Too many people think type erasure means "anything between angled brackets only exists at compile time". – ColinD Feb 20 '11 at 16:08
7

No, parameters retain their generic type information.

Type erasure is about an instance of List<T> not knowing what T is at execution time, for example. There's only really a List class - the rest is up to the compiler. But the compiler can use information about parameter types, and the type itself.

Here's an example:

import java.util.*;
import java.lang.reflect.*;

public class Test {

    public void foo(List<String> list) {
    }

    public static void main(String[] args) throws Exception{
        Method method = Test.class.getMethod("foo", List.class);
        Type parameterType = method.getGenericParameterTypes()[0];
        System.out.println(parameterType);
    }
}

This prints out:

java.util.List<java.lang.String>

So that type information has been retained in the metadata for the method.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • So, was it done like this for backward compatibility, as Hovercraft Full Of Eels suggests in his comment? – ElenaT Feb 20 '11 at 15:57