У меня есть следующий код:
import java.util.*;
public class Exmp {
public static void main(String[] args) {
List<Integer> integerList = Arrays.asList(1,2,3);
Gen gen = new Gen();
gen.m(integerList);
}
static class Gen<T>{
<T> void m(Collection<T> collection){
for (T s: collection) {
System.out.println(s);
}
}
void m(List<String> list){
for (String s: list) {
System.out.println(s);
}
}
}
}
Никак не могу понять почему вызывается метод со списком строк. Может кто ткнет носом?
Это поведение действительно является наследием до-дженериковой эры и относится к т.н. raw type:
To facilitate interfacing with non-generic legacy code, it is possible to use as a type the erasure (§4.6) of a parameterized type (§4.5) or the erasure of an array type (§10.1) whose element type is a parameterized type. Such a type is called a raw type.
More precisely, a raw type is defined to be one of:
The reference type that is formed by taking the name of a generic type declaration without an accompanying type argument list.
An array type whose element type is a raw type.
A non-static member type of a raw type R that is not inherited from a superclass or superinterface of R.
JLS 4.8
Raw type - это дженерик, использованный без указания типов; в данном случае raw type - это Gen<T>, который вы создаете как просто Gen. Т.к. вы не указываете тип, компилятор обрабатывает этот класс по-другому, "сбрасывая" всю generic-информацию, которую может найти:
The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C.
JLS 4.8
В том числе сбрасывается информация о List<String> и Collection<T>, методы теперь выглядят как просто m(List) и m(Collection). При выборе из этих двух методов компилятор выберет более подходящий - m(List), и получится ровно та ситуация, которую мы наблюдаем. Чтобы избежать этого, достаточно вывести Gen из-под понятия "raw type" - это можно сделать, либо указав произвольный тип (хватит даже Gen<?>), либо вообще его убрав - у вас и так параметризованный метод, поэтому параметр класса в принципе не нужен.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости