Автозаполнение 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>
Таким образом, информация о типе сохранена в метаданных метода.