java 中的泛型

发布时间:2026/11/5 17:39:42

java 中的泛型 概述泛型是在编译器工作编译完成后泛型信息会被擦除Type Erasure运行时 JVM 根本不知道你用了什么泛型。泛型主要是能在编译器校验类型是否安全并且能强制消除转换并能提高代码的复用率。泛型的作用泛型解决了三个核心问题类型安全编译期就能发现类型错误而不是等到运行时才爆ClassCastException消除强制转换不再需要手动(String) list.get(0)编译器自动插入转换代码代码复用一套逻辑适配多种数据类型避免为每种类型写重复代码// 没有泛型不安全需要手动强转 List list new ArrayList(); list.add(hello); String s (String) list.get(0); // 如果里面混入了 Integer运行时直接炸 // 有泛型编译期就能发现错误 ListString list new ArrayList(); list.add(hello); String s list.get(0); // 无需强转类型安全 // list.add(123); // 编译报错泛型接口、泛型类、泛型方法、泛型字段的定义泛型类在类名后声明类型参数整个类都可以使用public class BoxT { private T value; // 泛型字段 public void set(T value) { this.value value; } public T get() { return value; } } // 使用 BoxString strBox new Box(); strBox.set(hello); String s strBox.get(); // 无需强转 // 多类型参数 public class PairK, V { private K key; private V value; }泛型接口在接口名后声明类型参数public interface RepositoryT { void save(T entity); T findById(int id); } // 实现方式一指定具体类型 public class UserRepository implements RepositoryUser { Override public void save(User entity) { /* ... */ } Override public User findById(int id) { /* ... */ } } // 实现方式二延续泛型 public class GenericRepositoryT implements RepositoryT { Override public void save(T entity) { /* ... */ } Override public T findById(int id) { /* ... */ } }泛型方法类型参数声明在返回值之前独立于类的泛型参数public class Util { // 静态泛型方法不能引用类的泛型参数 public static T T getFirst(ListT list) { return list.get(0); } // 有界泛型方法 public static T extends Number double sum(T[] numbers) { double total 0; for (T num : numbers) { total num.doubleValue(); } return total; } } // 调用时编译器自动推断类型 Integer first Util.getFirst(List.of(1, 2, 3));泛型字段泛型字段定义在泛型类内部使用类声明的类型参数public class ContainerT { private T data; // 泛型字段 private ListT items; // 泛型集合字段 // ❌ 编译错误静态成员不能使用类的泛型参数 // private static T staticData; // ✅ 静态方法需要自己声明泛型参数 public static U U getDefault(U defaultValue) { return defaultValue; } }通配符通配符解决的是泛型灵活性问题——ListInteger不是ListNumber的子类泛型不支持协变通配符让 API 更灵活。通配符含义能读能写适用场景?任意类型Object只能 null只遍历不关心类型? extends TT 或其子类T只能 null生产者只读? super TT 或其父类ObjectT 及其子类消费者只写PECS 原则PECS 原则是 Java 泛型通配符使用的核心指导方针全称是 Producer Extends, Consumer Super意思是如果这个集合/容器是生产者只读用 ? extends T如果是消费者只写用 ? super T。? extends T上界通配符表示某个 T 或 T 的子类但具体是哪个子类编译器不知道。编译器只知道它是 T 的某个子类型但不知道具体是哪个写入时无法保证类型安全List? extends Number list new ArrayListInteger();这里list可能是ListInteger、ListDouble、ListFloat……编译器无法确定具体是哪个。? super T下界通配符表示某个 T 或 T 的父类但具体是哪个父类编译器不知道。编译器只知道它是 T 的某个父类但不知道具体是哪个可以写入但是可以读但是是Object,作用不大。List? super Integer list new ArrayListNumber();List? super Integer list new ArrayListNumber();这里 list 可能是 ListInteger、ListNumber、ListObject……编译器无法确定具体是哪个。PECS 原则总结角色含义通配符能做什么Producer生产者从中读取数据? extends T能get()不能add()Consumer消费者往里写入数据? super T能add()get()只能得到Object一句话记忆读用 extends写用 super。又取又放不用通配符用具体泛型。和T 的区别T类型参数定义类/方法时声明的确定类型占位符。调用时确定具体类型后方法内所有T都代表同一个类型。?通配符使用时表示未知类型。编译器不知道具体是什么只知范围。类型一致性T能确保多个参数类型一致?无法保证// T 保证 dest 和 src 元素类型相同 public T extends Number void copy(ListT dest, ListT src) { ... } // ? 无法保证两个 List 类型相同dest 可能是 ListIntegersrc 可能是 ListDouble public void copy(List? extends Number dest, List? extends Number src) { ... }读写能力T可读可写?受 PECS 原则限制但是T不能使用下界通配符// T 可读可写 public T extends Number void process(ListT list) { T item list.get(0); // 读 list.add(item); // 写 } // ? extends 只能读不能写 public void process(List? extends Number list) { Number item list.get(0); // 读 // list.add(new Integer(1)); // 写 编译报错编译器不知具体是 Integer 还是 Double }声明变量T可声明局部变量?不行public T extends Number void method1(ListT list) { T temp list.get(0); // ✅ } public void method2(List? extends Number list) { // ? temp list.get(0); // ❌ 无法用 ? 声明变量 Number temp list.get(0); // 只能退化为上界类型 }限定能力能力T?上界extends✅T extends Number✅? extends Number下界super❌ 不支持✅? super Number多重限定✅T extends A B❌ 不支持PESC(黄金法则)的应用场景生产者和消费者协同 — 经典Collections.copy这是 PECS 最经典的综合应用。src是生产者往外读dest是消费者往里写public static T void copy(List? super T dest, // 消费者往里写 List? extends T src) { // 生产者往外读 for (int i 0; i src.size(); i) { dest.set(i, src.get(i)); } } // 调用从 Integer 列表复制到 Number 列表 ListInteger src List.of(1, 2, 3); ListNumber dest new ArrayList(Arrays.asList(0, 0, 0)); Collections.copy(dest, src); // ✅ dest 是 Number能装下 Integer
延伸阅读

更多相关文章

2026/11/1 22:06:39

vue 弹窗组件挂载到指定元素内显示,,表格自适应弹窗宽高

在后台管理系统中,弹窗(Modal / Dialog)通常以全局浮层形式出现,覆盖整个页面。但在某些场景下,我们可能希望弹窗仅出现在某个特定区域(如某个卡片内、某个布局容器内),避免遮挡页面…

2026/11/5 16:51:33

EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析

1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被…

2026/11/5 16:26:13

Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6…

2026/11/5 15:00:49

基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享…

2026/11/5 14:10:30

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑