Подстановочный знак Java Generics — как я могу использовать generic с Lambda здесь?

#java #generics #lambda #java-8

#java #дженерики #лямбда — выражение #java-8

Вопрос:

Я пытаюсь создать универсальный метод. Мои dto:

 public class Master {
    private String string;
    private Date date;

    public String getString() {
        return this.string;
    }

    public Date getDate() {
        return this.date;
    }

    public void setString(String string) {
        this.string = string;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}
 

Мой дочерний класс, который расширяет Master, является:

 public class Child extends Master {

    private Date newDate;

    public Date getNewDate() {
        return this.newDate;
    }

    public void setNewDate(Date newDate) {
        this.newDate = newDate;
    }
}
 

Теперь, что я хочу сделать, это создать универсальный метод для получения —

 public static <T extends Master> Map<String, Map<Date, List<T extends Master>>> getRecalculateMasterMappedByInstrumentIdAndDate(List<T extends Master> masters) {
        return masters.stream().collect(Collectors.groupingBy(Child::getString, Collectors.groupingBy(x -> org.apache.commons.lang3.time.DateUtils.truncate(x.getDate(), Calendar.DAY_OF_MONTH))));
    }
 

Вышесказанное выдает мне ошибку во время компиляции. Как я могу написать универсальный метод для того же самого?

Комментарии:

1. Вы не можете использовать Child внутри метода, так как компилятор не знает об этом. Компилятор знает только Master . Либо удалите привязку, либо используйте Master только методы. Здесь абстрактный метод в master также поможет вам сделать это

Ответ №1:

Удалите привязку после объявления:

  • Возвращаемый тип: Map<String, Map<Date, List<T>>>
  • Тип параметра: List<T> masters .

Вы используете границы только с подстановочными знаками ( ? ) или в объявлении переменных типа.

Ответ №2:

Вы должны понимать разницу между объявлением переменной типа и использованием переменной типа. Когда вы пишете

 public static <T extends Master> Map<String, Map<Date, List<T>>>
    getRecalculateMasterMappedByInstrumentIdAndDate(List<T> masters) {
    …
}
 

<T extends Master> Объявляется переменная типа T , включающая ограничение , которое T должно быть подтипом Master . Другие вхождения T в пределах возвращаемого типа Map<String, Map<Date, List<T>>> и типа параметра List<T> используют переменную типа T и не нуждаются в повторении (и фактически не имеют права повторять) границ T .

Обратите внимание, что вы также должны использовать Master::getString в реализации метода, поскольку вы не можете предположить, что T это a Child . Это может быть Child , но вызывающий объект также может использовать Master или любой его подкласс для T . К счастью, getString это было определено в Master любом случае, так что вам не нужно Child здесь предполагать.

Ответ №3:

Я смог решить с помощью людей здесь. Спасибо, ребята. Мое решение:

 public static <T extends Master> Map<String, Map<Date, List<T>>> getMastersMappedByInstrumentIdAndDateForRecalculation(List<T> masters) {
        return masters.stream().collect(Collectors.groupingBy(Master::getString, Collectors.groupingBy(x -> org.apache.commons.lang3.time.DateUtils.truncate(x.getDate(), Calendar.DAY_OF_MONTH))));
    }