Класс списка, обернутый классом Map, не поддерживает универсальные типы в Java?

Определение класса

public interface ITest {
    Long foo();
}

public class Test implements ITest{

    @Override
    public Long foo() {
        return 0L;
    }
}

Методы

public Map<Long, List<? extends ITest>> moo() {
    List<Test> a = List.of(new Test());
    Map<Long, List<? extends ITest>> b = Map.of(1L, a);
    return b;
}

public Map<Long, List<? extends ITest>> koo() {
    List<Test> a = List.of(new Test());
    Map<Long, List<Test>> b = Map.of(1L, a);
    return b;
}

public List<? extends ITest> too() {
    List<Test> a = List.of(new Test());
    return a;
}

Я получаю ошибку только в функции koo(). Почему это не работает? Класс List, обернутый классом Map, не поддерживает дженерики?

Ниже приведена ошибка, которую я получаю.

Несовместимые типы. Найдено: 'java.util.Map<java.lang.Long,java.util.List<Test>>', требуется: 'java.util.Map<java.lang.Long,java.util.List<? расширяет ITest>>'

Я думаю, что это должно работать правильно, но это не так.

List<Test> не то же самое, что List<? extends ITest> (что бы ни было Test?) -- следовательно, Map<Long, List<Test>> нельзя использовать/возвратить как Map<Long, List<? extends ITest>> -- Map.of() и List.of() творят чудеса, они определяют правильный тип возвращаемого значения (если возможно)
user85421 29.05.2024 19:10

В вашем методе koo не используйте List<Test>, а используйте List<? extends ITest>. Это не одно и то же, но вы по какой-то причине ожидаете, что они будут одинаковыми.

f1sh 29.05.2024 19:12

Спасибо за ответ. Но вот чего я не понимаю, так это too работает, а koo не работает.. В чём разница? Метод too также возвращает объект List<Test>, но тип возвращаемого значения — List<? extends ITest>.

thekey.kim 29.05.2024 19:16

Я решил это благодаря вам. Я оценил тебя!

thekey.kim 29.05.2024 19:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
4
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш метод too компилируется, потому что List<Test> является подтипом объявленного возвращаемого типа метода List<? extends ITest>. Явный ? extends в возвращаемом типе делает List<Test> подтипом.

Ваш метод koo не компилируется, поскольку, хотя List<Test> является подтипом List<? extends ITest>, Map<Long, List<Test>> не является подтипом Map<Long, List<? extends ITest>>. Вложение этой связи дженериков в другой универсальный тип не допускается, поскольку вы используете инвариантные дженерики.

Если вы удалили ? extends из возвращаемого типа too, то этот метод не скомпилируется, поскольку List<Test> не является подтипом List<ITest>.

Например, то, что необходимо для too, добавьте ? extends к возвращаемому типу для koo, чтобы это скомпилировалось. Тип Map<Long, List<Test>> является подтипом Map<Long, ? extends List<? extends ITest>>, поэтому к нему добавлен ? extends.

//               vvvvvvvvv
public Map<Long, ? extends List<? extends ITest>> koo() {

Другие вопросы по теме