深入了解 Java 泛型

Java 泛型(Generics)是 Java SE 5 引入的一个强大特性,它允许你定义类、接口和方法时使用类型参数,从而使代码更加灵活和可重用。本篇博客将详细讲解 Java 泛型的概念、使用方法和注意事项,并通过多个代码示例,帮助新人快速理解和掌握泛型的使用。

一、什么是 Java 泛型?

泛型是参数化类型的一种机制,允许类、接口和方法在定义时使用类型参数,而在使用时再指定具体类型。这使得代码更加通用、类型安全并且易于维护。

1.1 泛型的优势
  • 类型安全:在编译时检测类型错误,减少运行时类型转换异常。
  • 代码重用:通过泛型编写的代码可以用于多种类型,减少冗余代码。
  • 可读性和可维护性:泛型代码更加清晰,容易理解和维护。
二、泛型类和泛型接口
2.1 定义泛型类

定义泛型类时,需要在类名后面添加类型参数。类型参数可以是单个字母(如 T)、多个字母(如 K, V)或具有描述性的名字。

public class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}
2.2 使用泛型类

在使用泛型类时,需要指定具体的类型参数。

public class Main {public static void main(String[] args) {Box<String> stringBox = new Box<>();stringBox.setContent("Hello");System.out.println(stringBox.getContent()); // 输出: HelloBox<Integer> integerBox = new Box<>();integerBox.setContent(123);System.out.println(integerBox.getContent()); // 输出: 123}
}
2.3 定义泛型接口

泛型接口的定义方式与泛型类类似。

public interface Pair<K, V> {K getKey();V getValue();
}public class OrderedPair<K, V> implements Pair<K, V> {private K key;private V value;public OrderedPair(K key, V value) {this.key = key;this.value = value;}public K getKey() {return key;}public V getValue() {return value;}
}public class Main {public static void main(String[] args) {Pair<String, Integer> pair = new OrderedPair<>("One", 1);System.out.println("Key: " + pair.getKey() + ", Value: " + pair.getValue()); // 输出: Key: One, Value: 1}
}
三、泛型方法
3.1 定义泛型方法

泛型方法是在方法定义中使用类型参数,类型参数放在方法返回类型前面。

public class Utility {public static <T> void printArray(T[] array) {for (T element : array) {System.out.print(element + " ");}System.out.println();}
}
3.2 调用泛型方法

在调用泛型方法时,编译器会根据传入的参数推断类型参数。

public class Main {public static void main(String[] args) {Integer[] intArray = {1, 2, 3};String[] strArray = {"A", "B", "C"};Utility.printArray(intArray); // 输出: 1 2 3 Utility.printArray(strArray); // 输出: A B C }
}
四、泛型边界
4.1 上界通配符

使用 extends 关键字定义泛型的上界,表示参数类型必须是指定类型或其子类。

public class Box<T extends Number> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}public class Main {public static void main(String[] args) {Box<Integer> integerBox = new Box<>();integerBox.setContent(123);System.out.println(integerBox.getContent()); // 输出: 123Box<Double> doubleBox = new Box<>();doubleBox.setContent(45.67);System.out.println(doubleBox.getContent()); // 输出: 45.67}
}
4.2 下界通配符

使用 super 关键字定义泛型的下界,表示参数类型必须是指定类型或其父类。

public class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}public class Utility {public static void addNumbers(Box<? super Integer> box) {box.setContent(123);}
}public class Main {public static void main(String[] args) {Box<Number> numberBox = new Box<>();Utility.addNumbers(numberBox);System.out.println(numberBox.getContent()); // 输出: 123}
}
五、通配符类型

通配符类型使用 ? 表示,在使用泛型类或接口时可以表示未知类型。

public class Utility {public static void printBox(Box<?> box) {System.out.println("Content: " + box.getContent());}
}public class Main {public static void main(String[] args) {Box<String> stringBox = new Box<>();stringBox.setContent("Hello");Utility.printBox(stringBox); // 输出: Content: HelloBox<Integer> integerBox = new Box<>();integerBox.setContent(123);Utility.printBox(integerBox); // 输出: Content: 123}
}
六、泛型的类型擦除

Java 泛型在编译时会进行类型擦除,这意味着在运行时泛型信息会被移除,所有类型参数都会被替换为其上界(如果没有指定上界,则替换为 Object)。

6.1 类型擦除的影响

类型擦除可能导致以下问题:

  • 类型安全检查的丢失:在运行时无法获取泛型类型参数的信息,可能导致类型转换异常。
  • 重载方法的冲突:由于类型擦除,不同的泛型方法在运行时可能冲突。
public class Main {public static void printList(List<String> list) {for (String element : list) {System.out.print(element + " ");}System.out.println();}// 会导致编译错误,因为类型擦除后签名相同// public static void printList(List<Integer> list) {//     for (Integer element : list) {//         System.out.print(element + " ");//     }//     System.out.println();// }public static void main(String[] args) {List<String> stringList = Arrays.asList("A", "B", "C");printList(stringList); // 输出: A B C }
}
6.2 避免类型擦除问题

为了避免类型擦除带来的问题,可以使用不同的方法名或显式地进行类型转换。

public class Main {public static void printStringList(List<String> list) {for (String element : list) {System.out.print(element + " ");}System.out.println();}public static void printIntegerList(List<Integer> list) {for (Integer element : list) {System.out.print(element + " ");}System.out.println();}public static void main(String[] args) {List<String> stringList = Arrays.asList("A", "B", "C");printStringList(stringList); // 输出: A B C List<Integer> integerList = Arrays.asList(1, 2, 3);printIntegerList(integerList); // 输出: 1 2 3 }
}
七、小结

通过这篇博客,我们详细讲解了 Java 泛型的概念、使用方法和注意事项。我们了解了如何定义和使用泛型类、泛型接口和泛型方法,以及如何设置泛型边界和使用通配符类型。我们还探讨了类型擦除带来的问题及其解决方案。

希望这篇博客能够帮助你快速理解和掌握 Java 泛型。如果你对泛型还有其他疑问或有更多的使用技巧,欢迎在评论区分享和讨论。记住,编程不仅仅是写代码,更是不断学习和交流的过程。Happy coding!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20898.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

回溯算法指组合总和

题目&#xff1a; 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 思路&#xff1a; 这种问题…

python编程:SQLite 管理图片数据库

在本博客中&#xff0c;我们将介绍如何使用 wxPython 和 sqlite3 模块构建一个 GUI 应用程序&#xff0c;该程序可以遍历指定文件夹中的所有图片&#xff0c;并将其信息存储到 SQLite 数据库中。 C:\pythoncode\new\InputImageOFFolderTOSqlite.py 项目简介 我们的目标是创建…

【无标题】2024.6.2

2024.6.2 【明霄升海平&#xff0c;飞彩镌流年。】 Sunday 四月廿六 A. 矩形覆盖 题目描述 有N个矩形&#xff0c;矩形的底边边长为1&#xff0c;且均在X轴上&#xff0c;高度给出&#xff0c;第i个矩形的高为h[i]&#xff0c;求最少需要几个矩形才能覆盖这个图形。 例如h […

微信里的东西怎么打印出来呢

随着微信的普及&#xff0c;我们的日常生活和工作都离不开这个强大的社交工具。无论是重要的工作文件、孩子的作业、还是精彩的旅行照片&#xff0c;我们都习惯在微信里保存和分享。但是&#xff0c;当需要将这些微信里的内容打印出来时&#xff0c;很多人可能会感到困惑和麻烦…

2024.05.18 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、实习 | 东风日产2024实习生招聘正式启动 实习 | 东风日产2024实习生招聘正式启动 2、实习 | 达实智能实习生招募令&#xff01; 实习 | 达实智能实习生招募令&#xff01; 3、校招 | …

电力能源指挥中心调度台解决方案主要关注的问题

调度台是指挥中心不可或缺的设备&#xff0c;随着信息化建设的不断深入&#xff0c;电力能源指挥中心已成为重要平台。因此&#xff0c;构建一套高效、智能的电力能源指挥中心调度台解决方案&#xff0c;需要关注以下关键问题&#xff1a; 一、实时监控与数据采集 电力能源指挥…

2.3.2_3 单链表的建立

喜欢《数据结构》部分笔记的小伙伴可以订阅专栏&#xff0c;今后还会不断更新。 此外&#xff0c;《程序员必备技能》专栏和《程序员必备工具》专栏&#xff08;该专栏暂未开设&#xff09;日后会逐步更新&#xff0c;感兴趣的小伙伴可以点一下订阅、收藏、关注&#xff01; 谢…

【AI 大揭秘】ChatGPT 写作绝技与必备提示词大全

利用ChatGPT撰写文章是一种极具创意的方法&#xff0c;它能显著提升您的写作效率&#xff0c;并帮助您创作出高质量的内容。通过人工智能的辅助&#xff0c;您可以迅速、便捷地生成精美文章&#xff0c;或至少为您的下一个写作项目提供灵感。 不管您是在撰写文章、剧本还是电子…

react路由参数path不再支持正则?比较v5和v6写法的差异性

文章目录 前言v5方式&#xff1a;直接在path参数中&#xff0c;写入对应正则&#xff08;1&#xff09;代码详细注释如下&#xff08;2&#xff09;页面输出如下&#xff0c;会出现undefined的情况 v6方式: 在路由对象中配置&#xff0c;但只可配动态路由&#xff0c;不可用正则…

TH方程学习(4)

一、背景介绍 在本节将会对TH方程打包成一个函数&#xff0c;通过输入目标星的轨道要素&#xff0c;追踪星在目标星VVLH坐标系下的相对位置和速度&#xff0c;以及预报的时间&#xff0c;得到预报时刻追踪星在VVLH坐标系下的位置和速度&#xff0c;以及整个状态转移矩阵。 合并…

替换所有的问号 ---- 模拟

题目链接 题目: 分析: 我们只需要遍历字符串, 将所有?进行修改即可但是需要判断, 修改的字符不能和前面后面重复同时, 有一个细节需要处理, 就是当?在最前面时, 没有前面的符号需要判断 在最后面的时候, 没有后面的字符需要判断 代码: class Solution {public String mod…

Django ORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

面试题--this关键字

this 指向是前端面试中的常问题型&#xff0c;简单分析为以下几种&#xff1a; 1. 在全局作用域中&#xff0c;this 关键字固定指向全局对象 window 或者 global。 2. 在函数作用域中&#xff0c;取决于函数是如何被调用的。 1&#xff09;函数直接调用&#xff0c;this 指向…

Leetcode 3169. Count Days Without Meetings

Leetcode 3169. Count Days Without Meetings 1. 解题思路2. 代码实现 题目链接&#xff1a;3169. Count Days Without Meetings 1. 解题思路 这一题的话我们只需要先对meeting的时间进行一下排序&#xff0c;然后不断更新当前连续开会的时间即可。当某一个会议开始时&#…

Java中lambda表达式是啥怎么使用

在Java中&#xff0c;Lambda表达式&#xff08;也称为闭包&#xff09;是一种简洁地表示匿名函数&#xff08;即没有名称的函数&#xff09;的方式。它们允许你将函数作为参数传递或赋值给变量&#xff0c;从而简化代码。Lambda表达式在Java 8及更高版本中引入。 Lambda表达式…

打造智能化未来:智能运维系统架构解析与应用实践

在数字化转型的大背景下&#xff0c;智能运维系统成为了企业提升效率、降低成本、增强安全性的关键利器。本文将深入探讨智能运维系统的技术架构&#xff0c;介绍其核心要素和应用实践&#xff0c;帮助读者全面了解智能运维系统的概念、优势和应用价值。 ### 1. 智能运维系统的…

如何进入 -MGMTDB目录

想想这个问题&#xff0c;大家可能觉得很简单吧&#xff0c;先不看答案&#xff0c;你试一试如何进去 1.问题现象&#xff1a; 我直接进入&#xff1a; cd -MGMTDB 直接就报错了&#xff1a; [gridhost03 _mgmtdb]$ cd -MGMTDB -bash: cd: -M: invalid option cd: usage: c…

Rust struct

Rust struct 1.实例化需要初始化全部成员变量2.如果需要实例化对象可变&#xff0c;加上mut则所有成员变量均可变 Rust支持通过已实例化的对象&#xff0c;赋值给未赋值的对象的成员变量 #![allow(warnings)] use std::io; use std::error::Error; use std::boxed::Box; use s…

【NumPy】深入解析numpy中的 iscomplex 方法

&#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a; 我是云天徽上&#xff0c;一名对技…

下载文件流

export function downloadFile(file, name, type) { const link document.createElement(‘a’) link.href window.URL.createObjectURL(new Blob([file], { type: type })) link.target ‘_blank’ link.download name document.body.appendChild(link) link.click() docu…