Я попытаюсь проиллюстрировать свою проблему в следующем упрощенном примере:
public class DataHolder<T> {
private final T myValue;
public DataHolder(T value) {
myValue = value;
}
public T get() {
return myValue;
}
// Won't compile
public <R> DataHolder<R super T> firstNotNull(DataHolder<? extends R> other) {
return new DataHolder<R>(myValue != null ? myValue : other.myValue); }
public static <R> DataHolder<R> selectFirstNotNull(DataHolder<? extends R> first,
DataHolder<? extends R> second) {
return new DataHolder<R>(first.myValue != null ? first.myValue : second.myValue);
}
}
Здесь я хочу написать общий метод firstNotNull
, который возвращает DataHolder
, параметризованный общим супертипом параметра типа T
аргумента this
и other
, поэтому позже я мог бы написать, например.
DataHolder<Number> r = new DataHolder<>(3).firstNotNull(new DataHolder<>(2.0));
или
DataHolder<Object> r = new DataHolder<>("foo").firstNotNull(new DataHolder<>(42));
Проблема заключается в том, что это определение firstNotNull
отклоняется компилятором с сообщением о том, что super T
часть ограничения типа является незаконной (синтаксически).
Однако без этого ограничения определение также неверно (очевидно), потому что в этом случае T
и R
не связаны друг с другом.
Интересно, что определение аналогичного статического метода selectFirstNotNull
является правильным, и последнее работает так, как ожидалось. Можно ли достичь такой же гибкости с помощью нестатических методов в системе типа Java?