Java与Kotlin泛型问题求助:Java子类继承Kotlin泛型父类疑问
Kotlin泛型类的Java继承问题解决方案
首先,我来帮你梳理这个Kotlin泛型类在Java中继承的核心问题,再给出明确的解决办法:
你的原始代码
Kotlin抽象父类
internal abstract class Parent<out T, in V> constructor(tList: List<T>, vList: List<V>) { abstract fun get(): List<T> abstract fun set(v: List<V>) }
未完成的Java子类
final class Child extends Parent<Number, String> { public Child(@NotNull List<? extends Number> tList, @NotNull List<? extends String> vList) { super(tList, vList); } @NotNull @Override public List<Number> get() { return ...; // 这里可能遇到编译问题或疑问 } }
核心问题分析
Kotlin的out/in泛型修饰符在Java中会被转换为协变(? extends)和逆变(? super)通配符,容易因匹配错误导致编译问题:
- 构造器参数不匹配:你给子类构造器第二个参数用了
List<? extends String>,但父类的in V泛型会让这个参数在Java中变成List<? super String>(逆变)——List<? extends String>是只读协变集合,无法赋值给需要可写的List<? super String>,这会直接触发编译错误。 - set方法未正确重写:你还没实现
set方法,即使写了也容易搞错参数类型,不符合重写规则。
修正后的Java子类代码
import org.jetbrains.annotations.NotNull; import java.util.List; final class Child extends Parent<Number, String> { // 构造器参数严格匹配父类编译后的签名:List<? extends T>, List<? super V> public Child(@NotNull List<? extends Number> tList, @NotNull List<? super String> vList) { super(tList, vList); } @NotNull @Override // 父类get()返回List<? extends Number>,返回List<Number>完全符合协变规则 public List<Number> get() { // 示例实现,可替换为你的业务逻辑 return List.of(1, 2.5, 3L); } @Override // 必须匹配父类set()的参数签名:List<? super String> public void set(List<? super String> v) { // 示例:可以安全向集合添加String元素,? super String允许写入String及其子类 v.add("Test Content"); } }
关键原理说明
out T(协变):在Java中对应? extends T,表示该泛型仅作为输出使用。所以父类构造器第一个参数可接受List<? extends T>(比如List<Integer>可传给List<? extends Number>),get()方法返回值也为List<? extends T>,你可以返回更具体的List<Number>甚至ArrayList<Number>。in V(逆变):在Java中对应? super V,表示该泛型仅作为输入使用。所以父类构造器第二个参数和set()方法参数都是List<? super V>,你可以传入List<Object>、List<CharSequence>或List<String>,这些集合都允许添加String类型元素。
内容的提问来源于stack exchange,提问作者J.ty
相关产品推荐
相关产品推荐

