137. Java 泛型 - 泛型与通配符:子类型化关系

2025-07-19  本文已影响0人  Cache技术分享

137. Java 泛型 - 泛型与通配符:子类型化关系

在 Java 中,泛型类和接口并不像普通类那样直接遵循继承规则。为了解决这个问题,我们可以使用通配符 (? extends T? super T) 来创建泛型类或接口之间的关系。本篇将详细解释如何使用通配符建立泛型类型之间的子类型关系,并通过示例帮助您理解。


1. 常规类的继承与泛型类型的关系

在普通类中,继承遵循子类型规则,即如果类 B 扩展类 A,则 BA 的子类型。您可以这样编写代码:

class A { /* ... */ }
class B extends A { /* ... */ }

B b = new B(); 
A a = b; // 合法,因为 B 是 A 的子类

🔍 子类型规则:


2. 泛型类型与子类型化

与常规类不同,泛型类型之间并不直接遵循子类型化规则。这意味着,即使 IntegerNumber 的子类,List<Integer> 也不是 List<Number> 的子类型,实际上这两者之间没有任何继承关系。

❌ 错误示例:

List<B> lb = new ArrayList<>();
List<A> la = lb;   // 编译错误:List<B] 不是 List<A> 的子类型

即使 BA 的子类,List<B> 并不等于 List<A>,这会导致编译错误。


3. 使用通配符解决泛型之间的子类型关系

为了建立泛型类型之间的关系,可以使用上限通配符 (? extends T) 来让 Java 编译器理解某个泛型类型是另一个泛型类型的子类型。

✅ 示例:List<Integer>List<Number> 之间的关系

IntegerNumber 的子类型,但是 List<Integer> 不是 List<Number> 的子类型。这是因为 泛型类型的子类型化并不自动传递。我们可以通过上限通配符来为 List<Integer>List<Number> 之间建立关系。

List<? extends Integer> intList = new ArrayList<>();
// 这是合法的,因为 List<? extends Integer> 是 List<? extends Number> 的子类型
List<? extends Number> numList = intList;

🔍 解析:


4. 上限通配符与下限通配符的关系

上限通配符(? extends T

下限通配符(? super T


5. 使用通配符创建泛型类型之间的关系

通过通配符,我们可以创建泛型类型之间的关系,使得代码更加灵活。以下是一些关键的泛型类型关系:

List<? extends Number> numList = new ArrayList<Integer>(); // 合法,因为 Integer 是 Number 的子类
List<? super Integer> objList = new ArrayList<Number>();  // 合法,因为 Integer 是 Number 的子类

6. 总结

通配符与泛型子类型化的要点:

通配符的实际应用:


7. 小贴士:通配符的使用场景


🎯 记住

上一篇 下一篇

猜你喜欢

热点阅读