
本文详解Java泛型中Function
本文详解java泛型中`function super number, ? extends string>`为何能安全接收`number`参数(如调用`shortvalue()`),却无法赋值给更具体的`function
在Java泛型中,? super T(下界通配符)常被误解为“可接受T及其所有父类”,但其真实语义是“该类型保证能安全处理T类型的输入”——这是关键前提。我们以如下代码为例分析:
Function super Number, ? extends String> func1 = obj -> String.valueOf(obj.shortValue()); Function<integer string> f2 = func1; // 编译错误!</integer>
✅ 为什么第一行不报错?——下界保障输入安全性
func1 的声明类型 Function super Number, ? extends String> 表示:
-
输入端(
? super Number):该函数能安全接收任何Number实例(如Integer、Double),因为无论实际类型是Number还是其子类,obj.shortValue()都合法(Number类定义了该方法); -
输出端(
? extends String):返回值是String或其子类型(实际上只有String),因此String.valueOf(...)返回的String完全兼容。
注意:此处的 ? super Number 并非要求你传入 Object 或 Serializable 等父类实例——编译器只允许你向 func1 传入 Number 及其子类(如 Integer),因为这是唯一能静态保证 shortValue() 可调用的范围。换言之,下界约束的是“可用性”,而非“可传入性”的上界。
❌ 为什么第二行报错?——类型系统拒绝逆向赋值
Function<integer string></integer> 要求:仅接受 Integer,且必须返回 String。
而 func1 的实际类型是 Function<number string></number>(由 lambda 推断),它虽能处理 Integer,但也能处理 Double、BigDecimal 等任意 Number 子类——这超出了 Function<integer string></integer> 的契约(后者承诺“只处理 Integer”)。
从类型关系看:
-
Function<number string></number>是Function super Integer, ? extends String>的子类型(因Number是Integer的父类,输入端逆变); - 但
Function<number string></number>不是Function<integer string></integer>的子类型——前者输入范围更宽,后者更窄,二者不可直接赋值。
类比理解:
“所有苹果都是水果”(
Apple ⊆ Fruit)成立;
但“所有水果都是苹果”(Fruit ⊆ Apple)不成立。
同理:Function<number string></number>可赋值给Function super Integer, ? extends String>,但绝不能赋值给Function<integer string></integer>。
✅ 正确做法:显式转换或重构类型
若需将 func1 赋给 f2,必须确保类型安全:
// 方案1:显式强制转换(不推荐,绕过类型检查) Function<integer string> f2 = (Function<integer string>) (Function, ?>) func1; // 方案2:直接定义为具体类型(推荐) Function<number string> func1 = obj -> String.valueOf(obj.shortValue()); Function<integer string> f2 = num -> func1.apply(num); // 安全调用</integer></number></integer></integer>
⚠️ 关键总结
-
? super T在函数输入位置体现逆变性(contravariance):更宽泛的输入类型可替代更具体的类型; - 函数赋值必须满足双向契约:左侧变量要求的输入范围不能比右侧实际支持的更窄,输出范围不能更宽;
- Lambda 表达式的实际类型由上下文推断,但通配符变量会隐藏具体类型,导致后续赋值受限——设计时应优先使用具体泛型类型,仅在需要泛化操作(如集合工具方法)时谨慎使用通配符。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











