Использование самоссылочных универсальных типов в Java - PullRequest
2 голосов
/ 05 июля 2019

Рассмотрим следующий метод Java:

<T extends List<T>> List<T> getMyList() {
    return Collections.emptyList();
}

Я могу присвоить ее вывод переменной с необработанным типом, например так:

List x = getMyList();
List<List> y = getMyList();

Но я не могу придумать, как назначить его вывод полностью параметризованному типу. В частности, я не могу вспомнить несобственный, конкретный тип T, который бы удовлетворял List<T> z = getMyList();

Можем ли мы создать такой T? Если нет, то почему?

Для контекста я создал этот вопрос, пытаясь понять, как Enums реализованы в Java.

Ответы [ 3 ]

0 голосов
/ 05 июля 2019

Не уверен, что я полностью понимаю ваш вопрос, но вот пример:

class Example<T> implements List<Example<T>> {
...
}
...
List<Example<String>> list = getMyList();
0 голосов
/ 05 июля 2019

Каждое перечисление в Java происходит от базового перечислимого класса Enum<T extends Enum<T>>, где T - фактический тип реализующего перечисления.

При написании SomeClass<T extends SomeClass<T>> вы можете убедиться, что параметр типа всегда является самим реализующим классом.

Допустим, у вас есть этот интерфейс:

public interface MyInterface<T extends MyInterface<T>> {

    T getSelf();
}

А это реализующий класс:

public class MyClass implements MyInterface<MyClass> {

    public MyClass getSelf() {
        return this;
    }
}

В MyClass невозможно использовать любой другой параметр типа, кроме самого MyClass.

0 голосов
/ 05 июля 2019

Вот пример конкретного типа, который и работает, и начинает намекать на возможный вариант использования (какая-то регистрация). Этот тип действует как экземпляр некоторого типа и как контейнер для всех экземпляров этого типа.

public class WeirdEnum extends AbstractList<WeirdEnum> {

  private static List<WeirdEnum> underlyingList = new ArrayList<>();

  @Override
  public WeirdEnum get(int index) { return underlyingList.get(index); }

  @Override
  public int size() { return underlyingList.size(); }

  static <T extends List<T>> List<T> getAList() {
    return Collections.emptyList();
  }

  public WeirdEnum() {
    underlyingList.add(this); // Sufficient for our example but not a good idea due to concurrency concerns.
  }

  static List<WeirdEnum> foo = WeirdEnum.getAList();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...