为何Function<U,B>无法传入接收Function<U,A>的getOrCreateA方法?
泛型方法参数不兼容问题分析与解决
问题背景
现有第三方库提供如下方法:
A getOrCreateA(Function<U, A> constructor) {}
已知B extends A,但在代码中传入Function<U, B>时,无法调用上述方法。同时,我需要实现特定类型的getOrCreate方法,当前代码报错:
public B getOrCreate_b(U ignore, Function<U,B> constructor) { A return_val = ignore.getOrCreate_a(constructor); // <- 报错 if (return_val instanceof B) return (B)return_val; else return constructor.apply(ignore); }
(注:已知若函数返回A则不会存储B,该问题已在其他逻辑中处理。)
原因分析
Java泛型默认是不变类型——即便B是A的子类,Function<U, B>和Function<U, A>之间也不存在继承关系。
Function<U, A>要求传入的函数必须能返回A类型(或其超类),但Function<U, B>只能保证返回B类型。虽然B是A的子类,但泛型系统不会自动推导这种兼容关系,只有当方法参数定义为Function<U, ? extends A>时,才能接受所有返回A子类的函数,但当前库方法并未使用通配符,因此无法直接传入Function<U, B>。
替代解决方案
我们可以手动将Function<U, B>适配为符合要求的Function<U, A>,利用B向上转型为A的特性,通过方法引用或lambda表达式实现适配:
修改后的代码
public B getOrCreate_b(U ignore, Function<U,B> constructor) { // 用方法引用将Function<U,B>转换为Function<U,A> A return_val = ignore.getOrCreate_a(constructor::apply); if (return_val instanceof B) return (B)return_val; else return constructor.apply(ignore); }
也可以使用lambda表达式写法,效果完全一致:
A return_val = ignore.getOrCreate_a(u -> constructor.apply(u));
两种写法都是让泛型系统明确感知:该函数返回的B可以安全向上转型为A,从而满足getOrCreate_a的参数要求。
内容的提问来源于stack exchange,提问作者slit bodmod
相关产品推荐
相关产品推荐

