Это не так, как это работает.Универсальный тип не означает «я не знаю, что я верну, мы увидим в зависимости от того, что я получу, что может быть что-то из списка, зависящего от реализации».Тип T
может быть переменным, но только во время реализации - во время выполнения он является фиксированным и может либо Boolean
, либо Integer
.
Так что вы можете сделать это
public interface Inverter<T> {
// variable return type, depending on argument
T invert(T toInvert);
}
с реализациями
class IntegerInverter implements Inverter<Integer> {
// return type is fixed to integer
Integer invert(Integer toInvert) {
return -toInvert.intValue();
}
}
class BooleanInverter implements Inverter<Boolean> {
// return type is fixed to boolean
Boolean invert(Boolean toInvert) {
return !toInvert.booleanValue();
}
}
Обратите внимание, что, вероятно, лучше повторно использовать существующие интерфейсы, например,
UnaryOperator<Integer> intInverter = i -> -i.intValue();
UnaryOperator<Boolean> boolInverter = b -> !b.booleanValue();
РЕДАКТИРОВАТЬ: предложение @Twometer приведет к чему-то вроде
class Inverters {
public static UnaryOperator<Integer> integerInverter() {
return i -> -i.intValue();
}
public static UnaryOperator<Boolean> boolInverter() {
return b -> !b.booleanValue();
}
// and maybe even this, but this will still require a cast
// at the client
public static <T> UnaryOperator<?> inverter(Class<T> clazz) {
if (clazz == Integer.class) {
return integerInverter();
} else if (clazz == Boolean.class) {
return boolInverter();
}
throw new IllegalArgumentException(String.format("Cannot create inverter for class %s", clazz));
}
}
Таким образом, у вас есть центральный способ получения необходимых вам инверторов;Таким образом, вы уверены, что они будут использованы повторно.Кроме того, вы можете кэшировать созданные лямбды, не изменяя код клиента.