You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java泛型下界疑问:func1创建合法却无法赋值给f2?

Java Function泛型赋值问题解析

问题描述

我对此存在困惑(错误出现在f2 = func1的赋值操作处):

  • 为何创建func1时未报错?我们调用了Number.shortValue(),但定义的下界是Number?
  • 若func1可以这样创建,为何无法将其赋值给f2?

相关代码

Function<? super Number, ? extends String> func1 = obj -> String.valueOf(obj.shortValue());
Function<Integer, String> f2 = func1;

报错信息

Incompatible types. Found: 'java.util.function.Function<capture<? super java.lang.Number>,capture<? extends java.lang.String>>', required: 'java.util.function.Function<java.lang.Integer,java.lang.String>'

问题解答

1. 创建func1时不报错的原因

func1的参数类型声明为? super Number,表示参数可以是Number或它的父类类型。但编译器处理Lambda表达式时,会自动推断出最具体的合法参数类型——这里Lambda体调用了shortValue()方法,只有Number及其子类拥有这个方法,所以obj被推断为Number类型。而Number属于? super Number的覆盖范围(通配符? super Number包含Number本身),因此Lambda与Function<? super Number, ? extends String>的类型完全兼容,不会触发编译错误。

2. 无法将func1赋值给f2的原因

这涉及到Java泛型的不变性以及协变/逆变规则:

  • Function<T, R>本身是不变类型,即Function<Number, String>和Function<Integer, String>之间不存在子类型关系,不能直接互相赋值。
  • 对于func1的类型Function<? super Number, ? extends String>:
    • 参数部分? super Number表示它能接受Number或其父类的参数,但f2要求的是能接受Integer参数的函数。虽然Integer是Number的子类,但逆变规则仅允许Function<Integer, String>赋值给Function<? super Integer, String>,反过来并不成立——编译器无法保证func1的参数类型能安全适配Integer的输入要求。
    • 返回值部分? extends String表示它返回String或其子类(虽然String是final类,实际只能是String),但协变规则仅允许Function<..., String>赋值给Function<..., ? extends String>,反过来也不成立。

综上,func1的带通配符类型与f2的具体类型不兼容,因此无法直接赋值。如果需要兼容,可以将f2的类型改为Function<? super Integer, ? extends String>,或者将func1的类型明确为Function<Number, String>后,通过通配符转换赋值(如Function<? super Integer, String> f2 = func1;)。

内容的提问来源于stack exchange,提问作者Khanna111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 13:46:04