Автозаполнение Eclipse - как это узнать о дженериках, когда доступна только двоичная банка?

Генераторы Java реализуются с использованием стирания типа. Это означает, что если у меня есть метод:

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

после компиляции, он будет в .class как:

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

У меня есть JAR файл с общими классами и методами, подобными приведенным выше. Это всего лишь двоичный файл. Никакого исходного кода нет ничего.

Но когда я использую его в коде, автозаполнение Eclipse дает мне setMapParam(Map<String, Integer> p), хотя в двоичном формате это как setMapParam(Map p).

Как Eclipse теперь тип (Map<String, Integer>), даже если подпись метода была стерта (до Map)? Или я что-то упускаю?

Ответ 1

Стирание типа не означает, что скомпилированный код не содержит информации о параметрах типа. Параметры типа, используемые в определениях классов и членов, присутствуют в скомпилированном коде и доступны через отражение (см. TypeVariable).

Какое средство стирания стилей состоит в том, что экземпляры объектов не имеют отдельных параметров типа. Учитывая определение класса MapImpl extends HashMap<T extends Comparable, Integer> и экземпляр этого класса, вы не можете узнать, какое конкретное значение T было использовано в коде, который создал экземпляр, потому что эта информация не существует. Но вы можете узнать, что это extends Comparable и что тип значения Integer, потому что эта информация является частью определения класса (и разделяется всеми экземплярами).

Ответ 2

Нет, параметры сохраняют общую информацию типа.

Стирание стилей - это пример List<T>, который не знает, что такое T во время выполнения, например. Там действительно класс List - остальное зависит от компилятора. Но компилятор может использовать информацию о типах параметров и самом типе.

Вот пример:

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);
    }
}

Это выдает:

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

Таким образом, информация о типе сохранена в метаданных метода.