Заменить недопустимые нижние границы в универсальном методе Java?

Я хотел бы сделать следующее:

public class ImmutableList {
  public  ImmutableList add(U element) { ... }
}

То есть, учитывая неизменяемый список T, вы можете добавить любой Uв список, чтобы получить неизменяемый список Uс ограничением, что Uдолжен быть супертипом T. Например

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

В теории это звучит великолепно, но нижняя граница Uнедопустима согласно JLS.Вместо этого я мог бы написать:

public class ImmutableList {
  public ImmutableList add(T element) { ... }
  public static  ImmutableList add(ImmutableList list, U element) { ... }
}

Таким образом, компилятор правильно выведет наименьшую верхнюю границу между типом элемента списка и U, который мы хотим добавить. Это законно. Это также отстой. Сравните:

// if 'U super T' were legal
list.add(monkey).add(human).add(rock);

// assuming 'import static ImmutableList.add'
add(add(add(list, monkey), human), rock);

Я большой поклонник функционального программирования, но я не хочу, чтобы мой Java-код выглядел как диалект Лиспа. Итак, у меня есть три вопроса:

  1. WTF? Почему привязка не является законной? Этот вопрос на самом деле задавался здесь раньше ( «Почему параметр типа Java не может иметь нижнюю границу?» ), но я думаю, что вопрос в том виде, в котором он сформулирован, несколько запутан, и ответы там сводятся к до «это недостаточно полезно», что я не очень-то понимаю.

  2. Раздел 4.5.1 JLSгласит: «В отличие от переменных обычного типа, объявленных в сигнатуре метода, при использовании подстановочного знака вывод типа не требуется. Следовательно, допустимо объявлять нижние границы подстановочного знака». Учитывая приведенную выше сигнатуру альтернативного метода static, компилятор явно способен вывести наименьшую верхнюю границу, которая ему нужна, поэтому аргумент кажется неверным. Кто-то может возразить, что это не так?

  3. Самое главное:Кто-нибудь может придумать законную альтернативу моей подписи метода с нижней границей? Вкратце цель состоит в том, чтобы код вызова выглядел как Java (list.add(monkey)), а не как Lisp (add(list, monkey)).

7
задан Community 23 May 2017 в 10:24
поделиться