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.