Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eclipse autocompletion - how does it know about generics when only binary jar is available?

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?

like image 220
ElenaT Avatar asked Feb 20 '11 15:02

ElenaT


2 Answers

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).

like image 144
Michael Borgwardt Avatar answered Oct 23 '22 10:10

Michael Borgwardt


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.

like image 7
Jon Skeet Avatar answered Oct 23 '22 09:10

Jon Skeet