Java泛型有界参数与自身不兼容,传入this触发类型错误如何解决
正确解决方式是将泛型参数T从方法级别迁移到类级别,采用奇异递归模板模式(CRTP)约束子类类型,具体实现如下:
父类Foo实现
import java.util.Optional; import java.util.function.BiConsumer; class Foo<T extends Foo<T>> { <V> void myself(final Optional<V> value, final BiConsumer<T, V> destination) { if (value.isPresent()) { destination.accept((T) this, value.get()); } } }
子类Bar实现
class Bar extends Foo<Bar> { void setAnswer(Integer toLife) { // 业务逻辑实现 } }
调用代码(可正常编译运行)
void outThere(Bar bar) { bar.myself(Optional.of(42), Bar::setAnswer); }
原写法报错原因说明
- 第一种方法级泛型写法:
T是方法调用时才确定的类型参数,编译器无法保证当前Foo实例this符合调用方指定的T类型边界,因此抛出类型不匹配错误。 - 第二种通配符写法:
? super Foo要求BiConsumer的第一个参数可接收任意Foo及父类实例,而Bar::setAnswer的第一个隐式参数必须是Bar类型,二者范围不匹配,因此方法引用无法适配。
可选安全校验
如果要避免错误的继承实现(如class Wrong extends Foo<Bar>这类不符合约定的写法),可以在Foo的构造函数中增加运行时类型校验:
import java.lang.reflect.ParameterizedType; public Foo() { Class<?> actualType = (Class<?>) ((ParameterizedType) getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; if (!actualType.equals(getClass())) { throw new IllegalArgumentException("Foo的子类必须将自身作为泛型参数传入"); } }
内容的提问来源于stack exchange,提问作者lucasvc
相关产品推荐
相关产品推荐

