Java дженерики и вилдкарды

233
22 марта 2018, 08:35

Кто-нибудь, объясните мне следующее поведение. Есть класс

public class ClassMap<T> extends LinkedHashMap<Class<? extends T>, T> {
    @SuppressWarnings("unchecked")
    public void put(T item) {
        put((Class<? extends T>) item.getClass(), item);
    }
}

есть два объекта этого класса

private ClassMap<ServerSchedule> serverTasks = new ClassMap<ServerSchedule>() {
    {
        put(...);
        put(...);
        put(...);
        put(...);
    }
};
private ClassMap<SensorIdSchedule> sensorTasks= new ClassMap<SensorIdSchedule>() {
    {
        put(...);
        put(...);
        put(...);
        put(...);
    }
};

Есть методы

public final Single<SyncCondition<ServerSchedule>> syncCondition() {
    return // Something
}

в ServerSchedule

и

public final Single<SyncCondition<? extends SensorIdSchedule>> syncCondition(String sensorId) {
    this.sensorId = sensorId;
    return syncCondition();
}
public abstract Single<SyncCondition<? extends SensorIdSchedule>> syncCondition();

в SensorIdSchedule

Вопрос же в следующем. Почему на вызов

List<SyncCondition<? extends SensorIdSchedule>> sensorConditions =
                            ListUtil.map(sensorTasks.keySet(), sClass -> sensorTasks.get(sClass).syncCondition(sensorId).blockingGet());

Компилятор не ругается, а на вызов

List<SyncCondition<? extends ServerSchedule>> serverConditions =
                            ListUtil.map(serverTasks.keySet(), sClass -> serverTasks.get(sClass).syncCondition().blockingGet());

ругается ещё как. Говорит что не List<SyncCondition<? extends ServerSchedule>> должен получаться, а List<Object>. Но для двух аследников Schedule всё сделано одинаково, в чем же разница?

PS Если это не очень понятно, то ListUtil.map() простой метод, который использует магию стримов, но скрывает ее реализацию:

public static <T, E> List<E> map(Collection<T> list, Function<? super T, ? extends E> function) {
    return StreamSupport.stream(list)
            .map(function)
            .collect(Collectors.toList());
}

UPDATED

Похоже дело в том, что ServerSchedule параметризован, добавил непараметризованную прослойку между Schedule и SensorSchedule (какой является и SensorIdSchedule) и компиятор перестал ругаться

public abstract class JustSchedule extends Schedule {
    public JustSchedule(Context context, HealbeClient healbeClient, long delay) {
        super(context, healbeClient, delay);
    }
    public abstract Single<SyncCondition<? extends JustSchedule>> syncCondition();
}
READ ALSO
Не получается вытянуть значение из JSON

Не получается вытянуть значение из JSON

получаю из JSON строку вида: {"base":"USD","date":"2018-03-01","rates":{"RUB":56839}} далее пытаюсь вытащить значение из RUB

205
JavaFX FXML Loader

JavaFX FXML Loader

Доброго времени сутокПодключил Maven к проекту и теперь MainCompare класс не может подгрузить fxml файл

244
Android TV, не работает Фокус в Webview на IFRAME

Android TV, не работает Фокус в Webview на IFRAME

Пишу приложение на андроид ТВ и не работает Фокус в Webview на IFRAMEПомогите

192
Как сделать анимацию по кругу?

Как сделать анимацию по кругу?

Как сделать анимацию, чтобы объект двигался по гругу?

220