Страницы

Поиск по вопросам

воскресенье, 7 июля 2019 г.

java Перегрузка методов и generic

У меня есть следующий код:
import java.util.*;
public class Exmp {
public static void main(String[] args) { List integerList = Arrays.asList(1,2,3); Gen gen = new Gen(); gen.m(integerList); }
static class Gen{
void m(Collection collection){ for (T s: collection) { System.out.println(s); } }
void m(List 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, который вы создаете как просто 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 и Collection, методы теперь выглядят как просто m(List) и m(Collection). При выборе из этих двух методов компилятор выберет более подходящий - m(List), и получится ровно та ситуация, которую мы наблюдаем. Чтобы избежать этого, достаточно вывести Gen из-под понятия "raw type" - это можно сделать, либо указав произвольный тип (хватит даже Gen), либо вообще его убрав - у вас и так параметризованный метод, поэтому параметр класса в принципе не нужен.

Комментариев нет:

Отправить комментарий