I have the following code:

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

I can not understand in any way why the method with the list of lines is caused. Can someone stick a nose?

1 answer 1

This behavior is indeed the heritage of the pre-generic era and refers to the so-called. raw type:

It is possible to make it possible to make it possible to facilitate interfacing with a non-generic type of a parameterized type (§4.5). . Such a type is called a raw type.

More precisely, one of the following types is:

  • An example of this is a generic type declaration of interest.

  • An element type whose element type is a raw type.

  • This is not inherited from the superclass or superinterface of R.

JLS 4.8

Raw type is a generic used without specifying types; in this case, the raw type is Gen<T> , which you create as just Gen Because you do not specify a type, the compiler treats this class differently, "dropping" all the generic information you can find:

The type of a constructor (§8.8), the instance method (§8.4, §9.4), or the non-static field (§8.3) the corresponding to C.

JLS 4.8

Including the information about List<String> and Collection<T> , the methods now look like just m(List) and m(Collection) . When choosing from these two methods, the compiler will choose a more suitable one - m(List) , and it will turn out exactly the situation that we observe. To avoid this, it is enough to deduce Gen from the notion of "raw type" - this can be done either by specifying an arbitrary type (even Gen<?> suffice), or by removing it altogether - you already have a parameterized method, therefore the class parameter not needed.