Страницы

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

пятница, 16 ноября 2018 г.

Почему тип дженрика нужно указывать второй раз при использовании {{}}?

Почему так можно:
ArrayList list = new ArrayList();
А так нельзя:
ArrayList list = new ArrayList(){{ add(0); }};
Почему так сделали?


Ответ

Используя так называемый double-brace initialization, вы создаёте новый анонимный класс. Когда в Java-7 разрешили опускать аргументы типа в некоторых случаях, одним из исключений, явно прописанным в стандарте, являются как раз анонимные классы:
It is a compile-time error if a class instance creation expression declares an anonymous class using the "<>" form for the class's type arguments.
Тут нет каких-то принципиальных ограничений, просто усложняло вывод типов в компиляторе, потому что есть много частных случаев. Поэтому недоделали. В Java-9 планируют исправить этот момент — смотрите баг JDK-8073593
В заключение скажу, что double-brace initialization — исключительно дурацкий способ инициализации объектов. У него могут быть неожиданные проблемы: от случайного захвата контекста внешнего класса до смены serialVersionID. В вашем случае это вообще не нужно. Пишите так:
List list = new ArrayList<>(Arrays.asList(0));
А если не собираетесь в будущем добавлять и удалять элементы в список, то лучше так:
List list = Arrays.asList(0);
Но даже если б у вас была Map, лучше заведите отдельный метод, фабрику или билдер, который создаёт предопределённые Map, но не делайте double-brace initialization.
В той же девятке, кстати, планируется упростить этот момент — смотрите JDK-8048330. Будет можно писать
List list = List.of(1,2,3,4); Set set = Set.of("aa", "bb", "cc"); Map map = Map.of("aa", 1, "bb", 2, "cc", 3);

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

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