当前位置: 首页 > news >正文

【Java实战经验】泛型-类型灵活使用与限制

欢迎来到啾啾的博客🐱。
录学习点滴,分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
欢迎评论交流,感谢您的阅读😄。

泛型

effective-java:29.优先考虑泛型 30.优先使用泛型方法

什么时候需要泛型呢?当需要限制类型,但又需要类型灵活不需要强制转换的场景。

泛型提供了Java常见异常ClassCastException的一个解法。即通过泛型约束对象类型返回,让强制类型转换时更安全、可读,也为编译器提供类型检查依据。
具体来说,泛型使用类型参数 Type Parameter,可以在编译时就制定并检查类型。

泛型实现机制

泛型的实现机制为类型擦除(Type Erasure)。

编译时编译器利用泛型信息进行类型检查,字节码生成时泛型信息会被擦除,无参<T>和有参<T extend ?>替换成上界。
当从泛型类中获取数据时,编译器会自动插入一个强制类型转换字节码指令。

无参泛型

以RouYi项目为例,无参泛型在项目中常见于通用Result类。
![[Pasted image 20250424115724.png]]

无参泛型T较Object在使用上的差异在于无参类型获取元素不需要进行强制类型转换,而是编译器进行了类型转换。可读性更高。

// 使用Object的不便
public class ObjectBox {private Object item;public void set(Object item) {this.item = item;}public Object get() {return item;}public static void main(String[] args) {ObjectBox box = new ObjectBox();box.set("Hello");box.set(123);//覆盖// 需要强制转换,且有风险Object retrieved = box.get();if (retrieved instanceof String) {String content = (String) retrieved; // 需要强制转换System.out.println(content.toUpperCase());} else if (retrieved instanceof Integer) {Integer num = (Integer) retrieved; // 需要强制转换System.out.println(num * 2); }// 如果不小心写错了转换类型,就会出问题String oops = (String) box.get(); // 如果 box.get() 返回的是 123, 这里会抛出 ClassCastException}
}// 使用泛型可以制定类型public class TBox<T> {private T item;public  void set(T item) {this.item = item;}public T get() {return item;}public static void main(String[] args) {// 实例化时制定参数类型TBox<String> tBox = new TBox();tBox.set("hello");tBox.set(123);// 编译错误!类型不匹配,无法将 int (Integer) 赋值给 StringTBox<Integer> intBox = new TBox<>(); // 指定 T 为 IntegerintBox.set(42); // OK}}

以上案例也可以解答为什么不建议使用原生类型(不带类型参数的泛型类型),如使用TBox时这样使用

TBox tbox = new TBox();
// 类似的还有
List lsit = new ArrayList<>();

这样泛型就没有类型检查约束、强制安全的意义了。

有参泛型

有参泛型有一个PECS法则:“Producer Extends, Consumer Super”。当你的泛型结构主要用于产出 (读取) T 类型的实例时,使用 ? extends T;当它主要用于消费 (写入) T 类型的实例时,使用 ? super T。如果既要读也要写,就不要用通配符,直接用 T。

上界通配符 ? extends T

表示“任何 T 或 T 的子类”。当你需要只从一个泛型集合中获取元素时,使用 extends。

List<? extends Number> numbers;//上界通配符可以让读取时类型安全。// 向上转型
for (Number num : numbers) { // 安全地读取为 Numbersum += num.doubleValue();
}

下界通配符 ? super T

表示“任何 T 或 T 的父类”。当你需要向一个泛型集合中添加 T 类型的元素时,使用 super。

List<? super Integer> list;// 子类可赋值给父类
list.add(Integer.valueOf(10));

PECS利用了Java的向上转型(Upcasting)和向下转型(Downcasting)的概念,算是一种高级应用和体现。

泛型总结

两个点:

  • 不要使用原生类型
  • PECS:Producer Extends, Consumer Super

相关文章:

  • flutter 小知识
  • BERT BERT
  • Nginx 安装与配置全流程指南(2025 最新版)
  • (树状数组)洛谷 P6119/P3657 Why Did the Cow Cross the Road II G/P 题解
  • QLExpress 深度解析:构建动态规则引擎的利器
  • 摘要 | 李录在北大光华管理学院的演讲《价值投资》
  • Spark-Streaming核心编程
  • Java集成【邮箱验证找回密码】功能
  • 聊聊Spring AI Alibaba的OneNoteDocumentReader
  • 实现Variant
  • AI赋能Python长时序植被遥感动态分析、物候提取、时空变异归因及RSEI生态评估
  • 系统高性能设计核心机制图解:缓存优化、链表调度与时间轮原理
  • 白鲸开源WhaleStudio与崖山数据库管理系统YashanDB完成产品兼容互认证
  • 麒麟系统离线安装软件方法(kazam录屏软件为例)
  • SEO的关键词研究与优化 第一章
  • AI | 最近比较火的几个生成式对话 AI
  • YOLO训练时到底需不需要使用权重
  • 【AI提示词】私人教练
  • 昆仑万维开源SkyReels-V2,解锁无限时长电影级创作,总分83.9%登顶V-Bench榜单
  • 使用正确的 JVM 功能加速现有部署
  • 中国与肯尼亚签署共同发展经济伙伴关系框架协定
  • 天问三号计划2028年前后发射实施,开放20千克质量资源
  • 商务部新闻发言人:截至目前,中美之间未进行任何经贸谈判
  • 王毅同伊朗外长阿拉格齐会谈
  • 明日出征!航天员详细信息来啦
  • 王励勤谈国乒备战洛杉矶奥运会:要对六块金牌制定新的战略