2026/4/18 20:48:33
网站建设
项目流程
如何改变wordpress的版面,芜湖网站优化公司,视频制作软件手机版,啦啦啦直播在线观看中文免费高清Java 泛型详解#xff08;2025–2026 面试/实战最实用版#xff09;
泛型#xff08;Generics#xff09;是 Java 5 引入的最重要特性之一#xff0c;到今天仍然是面试、代码审查、框架源码阅读中最常考察的点。
下面按从基础到高阶的顺序#xff0c;把最容易混淆、最常…Java 泛型详解2025–2026 面试/实战最实用版泛型Generics是 Java 5 引入的最重要特性之一到今天仍然是面试、代码审查、框架源码阅读中最常考察的点。下面按从基础到高阶的顺序把最容易混淆、最常踩坑、最有价值的内容全部梳理一遍。1. 为什么要有泛型最本质的两个原因类型安全编译期发现错误ListlistnewArrayList();list.add(hello);list.add(123);// 编译通过Strings(String)list.get(1);// 运行时 ClassCastException消除显式类型转换代码更简洁// 没有泛型Strings(String)list.get(0);// 有泛型ListStringlistnewArrayList();Stringslist.get(0);// 无需强转2. 泛型最核心的三种写法必须记住写法位置语法示例含义出现频率类/接口class BoxT类型参数 T定义在类/接口级别★★★★★方法E void print(E e)方法级类型参数独立于类泛型★★★★☆变量/参数ListString list使用时指定具体类型★★★★★3. 泛型擦除Erasure—— 面试必考点核心结论Java 泛型是编译期语法糖在编译后会被擦除类型参数被替换为 Object 或上界类型。擦除前后对比字节码层面// 源代码ListStringlistnewArrayList();list.add(hello);// 编译后大致ListlistnewArrayList();list.add(hello);// add(Object)Strings(String)list.get(0);擦除带来的重要影响常考运行时无法获得泛型具体类型ListStringlistnewArrayList();System.out.println(list.getClass()ArrayList.class);// trueSystem.out.println(listinstanceofListString);// 编译错误// 运行时只能判断原始类型System.out.println(listinstanceofList);// true静态变量/方法不能使用泛型类型参数classBoxT{staticTvalue;// 编译错误staticvoidset(Tt){}// 编译错误}不能创建泛型数组new T[]T[]arrnewT[10];// 编译错误4. 通配符Wildcard—— 最容易混淆的部分通配符写法含义能读get能写add经典使用场景List?任意类型只能得到 Object几乎不能写只能加 null作为只读参数List? extends NumberNumber 或其子类可以 get 为 Number不能写“生产者”Producer ExtendsList? super IntegerInteger 的父类包括 Integer只能得到 Object可以写 Integer 及其子类“消费者”Consumer Super经典面试题PECS 原则Producer Extends如果你要从集合中读取数据用? extendsConsumer Super如果你要向集合中写入数据用? super记忆口诀“读取用 extends写入用 super”5. 泛型方法最常被忽视但非常强大// 最常见的三种泛型方法写法// 1. 普通泛型方法最常用publicstaticTvoidprint(Tt){System.out.println(t);}// 2. 带返回值的泛型方法publicstaticTTgetFirst(ListTlist){returnlist.isEmpty()?null:list.get(0);}// 3. 泛型方法 多个类型参数publicstaticK,VMapK,VnewMap(){returnnewHashMap();}注意泛型方法前的T是方法级别的类型参数与类泛型无关。6. 泛型在集合框架中的真实用法面试常考// 生产者只读voidprintNumbers(List?extendsNumberlist){for(Numbern:list){// 安全读取System.out.println(n);}// list.add(1); // 编译错误}// 消费者只写voidaddIntegers(List?superIntegerlist){list.add(1);// 安全写入list.add(100);// OK// Integer x list.get(0); // 编译错误只能得到 Object}7. 2025–2026 年高频面试/实战问题为什么ListString不是ListObject的子类型类型不变量?、? extends T、? super T分别能干什么、不能干什么泛型擦除后如何实现类型安全编译器插入强制类型转换为什么静态方法/变量不能使用类泛型参数泛型数组为什么不允许new T[]可以用反射绕过但不推荐如何创建一个带有泛型类型的数组最安全写法(T[]) new Object[size]8. 一句话总结 记忆口诀一句话本质Java 泛型是编译期类型检查 语法糖运行时全部擦除为原始类型或上界类型靠编译器帮我们做类型转换。最实用口诀背下来就过关类写T用时指定类型方法写T独立于类泛型读取用extends写入用super运行时全擦除类型安全靠编译器静态成员别用 T数组创建别 new T如果你能手写下面三段代码就基本掌握泛型 80%带上下界的泛型方法PECS 原则的两个典型方法解释ListString为什么不能赋值给ListObject需要更深入哪一块比如泛型在反射中的真实写法签名擦除与桥接方法bridge method泛型在 Lambda / Stream 中的常见坑面试真题写一个泛型版的 max 函数随时告诉我我继续给你展开