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,并通过不同的类型参数创建不同的子类型。这些子类型之间仍然保持继承关系。
  • 类型参数的关系:泛型类或接口的类型参数决定了它们的继承关系和可赋值性。类型参数不匹配的泛型类型不能互相赋值。

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

相关推荐
sheji341625 分钟前
【开题答辩全过程】以 基于SpringBoot的疗养院管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
短剑重铸之日1 小时前
《设计模式》第六篇:装饰器模式
java·后端·设计模式·装饰器模式
0思必得01 小时前
[Web自动化] Selenium处理文件上传和下载
前端·爬虫·python·selenium·自动化·web自动化
码界奇点2 小时前
基于Flask与OpenSSL的自签证书管理系统设计与实现
后端·python·flask·毕业设计·飞书·源代码管理
phltxy2 小时前
Vue3入门指南:从环境搭建到数据响应式,开启高效前端开发之旅
前端·javascript·vue.js
小飞大王6662 小时前
CSS基础知识
前端·css
Charlie_lll3 小时前
学习Three.js–风车星系
前端·three.js
代码游侠3 小时前
学习笔记——Linux内核与嵌入式开发1
linux·运维·前端·arm开发·单片机·嵌入式硬件·学习
玩电脑的辣条哥3 小时前
幽灵回复AI已回复但前端不显示的排查与修复
前端·人工智能
石去皿3 小时前
轻量级 Web 应用 —— 把一堆图片按指定频率直接拼成视频,零特效、零依赖、零命令行
前端·音视频