Невозможно присвоить результат, возвращаемый методом, который получает общий список и возвращает список<?>

Я пытаюсь отфильтровать список объектов, реализующих интерфейс. И я пытаюсь создать общий метод для всех классов.

Что-то вроде:

interface SomeInterface {
    String getFlag();
}


class SomeObject implements SomeInterface {
    public String getFlag() {
        return "X";
    }
}


List<SomeObject> someObjectList = new ArrayList<>();

// Compilation error here
List<SomeObject> filterList = filterGenericList(someObjectList, "X");


private List<?> filterGenericList(List<? extends SomeInterface> objects, String flag) {
        return objects.stream()
                .filter(it -> it.getFlag().equals(flag))
                .collect(Collectors.toList());
}

Как убежать от ошибки компиляции?

 Incompatible types. 
 Found: 'java.util.List<capture<?>>', 
 Required: 'java.util.List<SomeObject>'

Почему вы ожидаете, что результатом filterGenericList будет List<SomeObject>? Ваш метод не говорит об этом, он говорит, что возвращает список что-либо.

Louis Wasserman 13.05.2022 01:16

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

Victor Soares 13.05.2022 01:18
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
46
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Когда вы возвращаете List<?>, это означает, что метод возвращает список неизвестного типа. Java не знает, что это тот же тип списка, что и входной список. Чтобы сигнализировать об этом, создайте общий тип T и сделайте входной и выходной списки List<T>.

private <T extends SomeInterface> List<T> filterGenericList(List<T> objects, String flag) {
    return objects.stream()
        .filter(it -> it.getFlag().equals(flag))
        .collect(Collectors.toList());
}

Неограниченный подстановочный знак<?>, также называемый неизвестный тип, — это способ сообщить компилятору, что общий тип нельзя предсказать, и поэтому компилятор не позволит присвоить список неизвестный тип списку SomeObject, потому что невозможно гарантировать, что это назначение безопасно. .

Если у вас есть список объектов, принадлежащих к разным классам, реализующим SomeInterface, чтобы различать их, вы можете явно передать экземпляр целевого класса Class<T> в метод в качестве аргумента.

Похоже, вы пытаетесь заново изобрести тот же механизм, используя метод getFlag(). Это не выглядит надежным, потому что ничто не может помешать вам сделать опечатку или случайно реализовать getFlag() в двух разных классах таким образом, чтобы возвращалось одно и то же значение.

private <T extends SomeInterface> List<T> filterGenericList(List<? extends SomeInterface> objects, 
                                                            Class<T> targetClass) {
    return objects.stream()
        .filter(it -> targetClass.isAssignableFrom(it.getClass()))
        .map(targetClass::cast)
        .collect(Collectors.toList());
}

во-первых, List<?> не содержит никакой информации о типе. Вы ожидаете список SomeObject, но ваш метод просто возвращает список любого типа.

Для достижения вашей цели вы должны определить свой метод фильтра как

private static  <T extends SomeInterface> List<T> filterGenericList(List<T> objects, String flag)

Таким образом вы гарантируете, что возвращаемый список имеет тот же тип, что и входной список.

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