Почему использование Collections.emptySet() с дженериками работает в задании, но не как параметр метода? - программирование
Подтвердить что ты не робот

Почему использование Collections.emptySet() с дженериками работает в задании, но не как параметр метода?

Итак, у меня есть класс со следующим конструктором:

public FilterList(Set<Integer> labels) {
    ...
}

и я хочу построить новый объект FilterList с пустым множеством. Следуя совету Джошуа Блоха в своей книге "Эффективная Java", я не хочу создавать новый объект для пустого набора; Я просто использую Collections.emptySet() вместо:

FilterList emptyList = new FilterList(Collections.emptySet());

Это дает мне ошибку, жалуясь, что java.util.Set<java.lang.Object> не является java.util.Set<java.lang.Integer>. ОК, как насчет этого:

FilterList emptyList = new FilterList((Set<Integer>)Collections.emptySet());

Это также дает мне ошибку! Хорошо, как насчет этого:

Set<Integer> empty = Collections.emptySet();
FilterList emptyList = new FilterList(empty);

Эй, это работает! Но почему? В конце концов, у Java нет вывода типа, поэтому вы получаете предупреждение о непроверенных преобразованиях, если вы делаете Set<Integer> foo = new TreeSet() вместо Set<Integer> foo = new TreeSet<Integer>(). Но Set<Integer> empty = Collections.emptySet(); работает даже без предупреждения. Почему это?

4b9b3361

Ответ 1

Короткий ответ - это ограничение вывода типа в общей системе Java. Он может вызывать общие типы против конкретных переменных, но не против параметров метода.

Я подозреваю, что это связано с тем, что методы динамически отправляются в зависимости от класса среды выполнения объекта-владельца, поэтому во время компиляции (когда разрешена все общая информация) вы не можете точно знать, что класс параметра метода будет и, следовательно, не может быть выведен. Объявления переменных хороши и постоянны, поэтому вы можете.

Кто-то еще может предоставить более подробную информацию и/или хорошую ссылку.: -)

В любом случае вы всегда можете указать параметры типа явно для общих вызовов, например:

Collections.<Integer>emptySet();

или даже несколько параметров одновременно, например

Collections.<String, Boolean>emptyMap(); // Returns a Map<String, Boolean>

Это часто выглядит немного чище, чем бросать, в тех случаях, когда вывод не срабатывает.

Ответ 2

попробуйте

FilterList emptyList = new FilterList(Collections.<Integer>emptySet());

Вы можете принудительно ввести параметр типа для методов, которые имеют их, в случаях, когда вывод недостаточно хорош, или чтобы вы могли использовать подтипы; например:

// forces use of ArrayList as parameter instead of the infered List
List<String> l = someObject.<ArrayList<String> methodThatTakesTypeParamForReturnType();

Ответ 3

Вы хотите сделать это:

FilterList emptyList = new FilterList(java.util.Collections.<Integer>emptySet());

Это указывает методу emptySet, что его общий параметр должен явно указывать на Integer вместо стандартного Object. И да, синтаксис полностью фанковый и неинтуитивный для этого.:)