Насколько я знаю, Java передает информацию о аргументах родового типа во время выполнения. Он используется только для компиляции для выполнения проверок, например, является ли этот конкретный вызов метода действительным или нет.
Сегодня я натолкнулся на следующий фрагмент кода, в котором, по-видимому, Java определяет аргумент типа collection/list, какой конструктор вызывает:
public static class MyClass {
public MyClass(final Collection<String> coll) {
System.out.println("Constructor 1");
}
public MyClass(final List<Integer> list) {
System.out.println("Constructor 2");
}
}
Выполняются следующие вызовы:
new MyClass(new HashSet<String>()); // Constructor 1
new MyClass(new ArrayList<String>()); // Constructor 1
new MyClass(new ArrayList<Integer>()); // Constructor 2
Теперь, если я стираю аргументы типа:
public static class MyClass2 {
public MyClass2(final Collection coll) {
System.out.println("Constructor 1");
}
public MyClass2(final List list) {
System.out.println("Constructor 2");
}
}
... Те же призывы действуют, как я ожидал бы от них; вызов конструктора, который использует аргумент list, подходит для конструктора, который наиболее точно отвечает его потребностям:
new MyClass2(new HashSet<String>()); // Constructor 1
new MyClass2(new ArrayList<String>()); // Constructor 2
new MyClass2(new ArrayList<Integer>()); // Constructor 2
Похоже, что информация обобщений хранится в скомпилированном классе (в данном случае MyClass) и не отбрасывается в конце концов, но ее следует отбросить. Что я не понимаю?