127. Java 泛型 - 泛型类与子类型

127. Java 泛型 - 泛型类与子类型

1. 泛型类和接口的子类型化

在 Java 中,可以通过扩展或实现泛型类或接口来对其进行子类型化 。这意味着,如果一个类或接口是泛型的,它的类型参数将影响该类或接口的子类型关系。这个关系通过 extendsimplements 子句来决定。

示例:ArrayListList

考虑 Java 的 Collections 类库,ArrayList<E> 实现了 List<E>,而 List<E> 又扩展了 Collection<E>。因此,ArrayList<String>List<String> 的子类型,而 List<String> 又是 Collection<String> 的子类型。这是泛型类之间子类型关系的一种体现。

java 复制代码
List<String> list = new ArrayList<>();  // OK, ArrayList<String> 是 List<String> 的子类型

这就表明,当不改变类型参数时,泛型类之间会保持子类型关系。ArrayList<String>List<String> 的子类型,而 List<String> 又是 Collection<String> 的子类型。

2. 自定义泛型接口的子类型化

假设我们需要定义一个自定义的泛型接口 PayloadList,它将泛型类型 P 的值与每个元素相关联。例如,这个接口可能声明如下:

java 复制代码
interface PayloadList<E, P> extends List<E> {
    void setPayload(int index, P val);
    // 其他方法
}

在这个接口中,E 代表列表元素的类型,P 代表与每个元素相关联的"有效负载"类型。

示例:泛型接口的子类型

接下来,我们可以创建 PayloadList 的具体类型参数化版本:

java 复制代码
PayloadList<String, String> stringPayloadList = new SomePayloadListImpl<>();
PayloadList<String, Integer> integerPayloadList = new SomePayloadListImpl<>();
PayloadList<String, Exception> exceptionPayloadList = new SomePayloadListImpl<>();
  • PayloadList<String, String>List<String> 的子类型。
  • PayloadList<String, Integer>List<String> 的子类型,尽管它使用了不同的泛型类型参数。
  • PayloadList<String, Exception> 也是 List<String> 的子类型,尽管它的第二个类型参数是 Exception

解释

这里的核心概念是:只要不改变类型参数之间的相对关系,泛型类型之间就能保留子类型关系 。即使我们在泛型接口 PayloadList 中使用不同的类型参数,它们依然可以和 List<String> 保持子类型关系。关键是,类型参数 E 的一致性确保了我们可以将 PayloadList<E, P> 类型的对象赋值给 List<E> 类型的变量。

3. 泛型类和接口的类型参数

泛型类和接口的类型参数与它们的子类型关系密切相关。类型参数不仅决定了接口或类的功能,还影响了它们的继承关系和泛型约束。例如,不能将 PayloadList<String, String> 直接赋值给 PayloadList<Integer, Integer>,即使这两个类型都继承自 List<String>,因为它们的第二个类型参数不同。

java 复制代码
PayloadList<String, String> list1 = new SomePayloadListImpl<>();
PayloadList<Integer, Integer> list2 = new SomePayloadListImpl<>();

// 这将会报错,因为 list1 和 list2 不是相同类型,即使它们都继承自 List<String>。
list1 = list2;  // 编译错误,类型参数不同

4. 总结

  • 泛型类和接口的子类型化 :泛型类或接口的子类型关系由类型参数确定。只要不改变类型参数之间的关系,子类型关系就能保留。例如,ArrayList<String>List<String> 的子类型,而 List<String> 又是 Collection<String> 的子类型。
  • 自定义泛型接口 :我们可以定义自己的泛型接口,如 PayloadList,并通过不同的类型参数创建不同的子类型。这些子类型之间仍然保持继承关系。
  • 类型参数的关系:泛型类或接口的类型参数决定了它们的继承关系和可赋值性。类型参数不匹配的泛型类型不能互相赋值。

通过理解这一点,学员可以更好地理解泛型类和接口之间的继承关系,以及如何自定义泛型接口和确保类型安全。

相关推荐
大怪v5 小时前
AI抢饭?前端佬:我要验牌!
前端·人工智能·程序员
新酱爱学习5 小时前
字节外包一年,我的技术成长之路
前端·程序员·年终总结
小兵张健5 小时前
开源 playwright-pool 会话池来了
前端·javascript·github
IT_陈寒8 小时前
Python开发者必知的5大性能陷阱:90%的人都踩过的坑!
前端·人工智能·后端
codingWhat9 小时前
介绍一个手势识别库——AlloyFinger
前端·javascript·vue.js
代码老中医9 小时前
2026年CSS彻底疯了:这6个新特性让我删掉了三分之一JS代码
前端
不会敲代码19 小时前
Zustand:轻量级状态管理,从入门到实践
前端·typescript
踩着两条虫9 小时前
VTJ.PRO 双向代码转换原理揭秘
前端·vue.js·人工智能
扉川川9 小时前
OpenClaw 架构解析:一个生产级 AI Agent 是如何设计的
前端·人工智能
远山枫谷9 小时前
一文理清页面/组件通信与 Store 全局状态管理
前端·微信小程序