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

深入理解Jdk5引入的Java泛型:类型安全与灵活性并存

深入理解Jdk5引入的Java泛型:类型安全与灵活性并存

在这里插入图片描述

​ 在Java的中,有一个强大的工具,它可以让你在编写代码时既保持类型安全,又享受灵活性。**这个工具就是——泛型(Generics)。**本文将引导你深入了解Java泛型的奥秘,让你从此编写更强大、更安全的代码。

基本概念:

泛型是什么?

​ 泛型是Java中的一项强大功能,它允许你编写能够处理多种数据类型的类、接口和方法。通过使用泛型,你可以将数据类型作为参数传递给类或方法,从而实现更高层次的代码重用和类型安全。

Java 泛型(generics)本质是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

假定我们有这样一个需求:写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?

答案是可以使用 Java 泛型

使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整型数组、浮点数数组、字符串数组等进行排序。


泛型类和泛型方法

泛型在Java中有两种主要形式:泛型类和泛型方法。泛型类是具有一个或多个类型参数的类,而泛型方法是在调用时可以接受不同类型参数的方法。


泛型类的基本概念

泛型类是一种允许在创建类的实例时指定数据类型的类。通过使用泛型,你可以将类的数据类型参数化,从而使得类可以适用于多种数据类型。让我们来看一个简单的例子:一个通用的容器类Box

public class Box<T> {private T content;public Box(T content) {this.content = content;}public T getContent() {return content;}public void setContent(T content) {this.content = content;}
}

在上面的示例中,我们定义了一个泛型类Box,它可以存储任意类型的数据。T是一个类型参数,它在实例化Box对象时确定。

使用泛型类

现在,让我们看看如何使用泛型类Box来存储不同类型的数据。

public class GenericClassExample {public static void main(String[] args) {Box<Integer> intBox = new Box<>(42);//存储整数int intValue = intBox.getContent();System.out.println("Integer value: " + intValue);Box<String> stringBox = new Box<>("Hello, Stevedash!");//存储字符串String stringValue = stringBox.getContent();System.out.println("String value: " + stringValue);}
}

在上述示例中,我们创建了两个Box对象,一个存储整数,另一个存储字符串。通过使用泛型类,我们可以在编译时就确保数据类型的正确性,避免了在运行时出现类型错误。


类型安全与重用性

泛型类不仅提供了类型安全性,还增加了代码的重用性。你可以轻松地创建适用于不同类型的通用类,减少了代码的冗余。这使得你的程序更加健壮、可维护。


泛型类的限制

虽然泛型类非常强大,但也有一些限制。例如,无法创建泛型数组,也不能使用基本数据类型作为泛型参数(需要使用对应的包装类)。

自定义泛型类

除了使用Java提供的泛型类,你还可以自定义泛型类来满足特定需求。通过实现自己的泛型类,你可以更好地理解泛型的原理,以及如何灵活地使用它。


泛型方法

你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

下面是定义泛型方法的规则:

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的 )。

  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。

  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。

  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像 int、double、char 等)。


    java 中泛型标记符:

  • E - Element (在集合中使用,因为集合中存放的是元素)

  • T - Type(Java 类)

  • K - Key(键)

  • V - Value(值)

  • N - Number(数值类型)

  • ? - 表示不确定的 java 类型


下面的例子演示了如何使用泛型方法打印不同类型的数组元素:

实例

public class GenericMethodTest
{// 泛型方法 printArray                         public static < E > void printArray( E[] inputArray ){// 输出数组元素            for ( E element : inputArray ){        System.out.printf( "%s ", element );}System.out.println();}public static void main( String args[] ){// 创建不同类型数组: Integer, Double 和 CharacterInteger[] intArray = { 1, 2, 3, 4, 5 };Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };System.out.println( "整型数组元素为:" );printArray( intArray  ); // 传递一个整型数组System.out.println( "\n双精度型数组元素为:" );printArray( doubleArray ); // 传递一个双精度型数组System.out.println( "\n字符型数组元素为:" );printArray( charArray ); // 传递一个字符型数组} 
}

编译以上代码,运行结果如下所示:

整型数组元素为:
1 2 3 4 5 双精度型数组元素为:
1.1 2.2 3.3 4.4 字符型数组元素为:
H E L L O 

在这段代码中,虽然我们使用了泛型方法printArray来输出不同类型的数组元素,但实际上并没有创建一个泛型数组。我们只是在使用已有的数组来进行迭代遍历并输出元素,而不是通过泛型参数创建新的数组。


在Java中,直接创建一个泛型数组是不允许的。例如,以下代码是不合法的:

// 这是不合法的,无法直接创建泛型数组
T[] array = new T[10];

​ 泛型数组的限制是为了确保类型安全性。虽然在代码中使用了泛型方法,但我们并没有在代码中直接创建泛型数组,而是使用了已有的数组。因此,虽然代码中有泛型方法,但没有涉及创建泛型数组的情况。


通配符和边界

泛型还支持通配符和边界的概念,让你能够更精细地控制泛型类型的范围。通配符?表示未知类型,而边界则限制了允许传递的类型范围。

import java.util.List;public class GenericWildcard {/*** 打印通配符类型的列表元素** @param list 要打印的列表*/public static void printList(List<?> list) {for (Object element : list) {System.out.print(element + " ");}System.out.println();}/*** 计算数字类型列表的总和** @param list 要计算总和的列表* @return 列表元素的总和*/public static <T extends Number> double sumOfList(List<T> list) {double sum = 0;for (T element : list) {sum += element.doubleValue();}return sum;}//<T extends Number>: 这是泛型类型参数的声明。在这里,<T> 表示泛型类型参数的名称,你可以在方法体内使用它来代表实际的数据类型。extends Number 是一个泛型类型的限定符。它的意思是,类型参数 T 必须是 Number 类或其子类。这样做的目的是为了确保列表中的元素都是数字类型,以便在方法中进行数字运算。public static void main(String[] args) {// 创建一个包含不同类型元素的列表List<?> wildcardList = List.of("Hello", 42, 3.14, 'A');// 打印通配符类型的列表元素System.out.print("通配符列表元素:: ");printList(wildcardList);// 创建一个数字类型的列表List<Integer> integerList = List.of(1, 2, 3, 4, 5);// 计算数字类型列表的总和double sum = sumOfList(integerList);// 输出计算结果System.out.println("整数列表总和: " + sum);}
}

​ 输出结果如下:

通配符列表元素: Hello 42 3.14 A 
整数列表总和: 15.0

​ 上面的示例演示了一个使用通配符的方法printList和一个使用边界的方法sumOfList。通配符使方法能够接受不同类型的列表,而边界则限制了方法只能接受继承自Number的类型列表。

泛型与集合框架

Java的集合框架(如List、Set、Map等)广泛使用了泛型,使得集合中的元素类型可以更加明确和安全。使用泛型可以在编译时捕获类型错误,避免在运行时出现类型转换异常。


最后总结:

​ Java泛型是一项强大的功能,它既保持了类型安全,又提高了代码的灵活性和重用性。通过学习泛型的使用,能够编写更强大、更安全的代码,让我们的程序更加健壮和可维护。

总结一下泛型类的优缺点:

泛型类的优点:

  1. 类型安全性: 泛型类在编译时可以检查数据类型,从而提前发现类型错误,避免了在运行时出现类型转换异常。
  2. 代码重用性: 泛型类允许你创建通用的数据结构,适用于多种数据类型,减少了代码的冗余,提高了代码的重用性。
  3. 灵活性: 泛型类使得你可以创建适用于不同数据类型的通用类,从而在不同场景下实现灵活的数据存储和处理。
  4. 编译时类型检查: 泛型类使得编译器能够检查和强制确保类型的正确性,从而提高了代码的可靠性和稳定性。
  5. 更好的可读性: 使用泛型类可以提供更清晰的代码结构和命名,使得代码更易于理解和维护。

泛型类的缺点:

  1. 类型参数限制: 泛型类无法直接使用基本数据类型作为类型参数,需要使用对应的包装类。同时,无法创建泛型数组。
  2. 复杂性: 对于初学者来说,泛型的概念可能会有一定的复杂性,需要一些时间来理解和掌握。
  3. 编译时错误信息: 有时,编译器产生的泛型相关的错误信息可能不够直观,需要花时间来解读和修复。
  4. 擦除和类型擦除: 泛型类在编译时会进行类型擦除,这可能会导致在某些情况下失去一些类型信息。
  5. 部分场景不适用: 在某些特定的场景下,泛型类可能不适用,需要根据实际需求来选择是否使用泛型。

​ 尽管泛型类存在一些缺点,但它的优点远远超过了缺点,可以帮助我们写出更安全、更灵活、更高效的代码。

作者:Stevedash

发表于:2023年8月8日15点19分

来源:Java 泛型 | 菜鸟教程 (runoob.com)

注:本文内容基于个人学习理解,如有错误或疏漏,欢迎指正。感谢阅读!如果觉得有帮助,请点赞和分享。

相关文章:

深入理解Jdk5引入的Java泛型:类型安全与灵活性并存

深入理解Jdk5引入的Java泛型&#xff1a;类型安全与灵活性并存 ​ 在Java的中&#xff0c;有一个强大的工具&#xff0c;它可以让你在编写代码时既保持类型安全&#xff0c;又享受灵活性。**这个工具就是——泛型&#xff08;Generics&#xff09;。**本文将引导你深入了解Java…...

idea在控制台中输出文字显示乱码

VM options中加入下面这行 -Dfile.encodingutf-8...

hacksudo3 通关详解

环境配置 一开始桥接错网卡了 搞了半天 改回来就行了 信息收集 漏洞发现 扫个目录 大概看了一眼没什么有用的信息 然后对着login.php跑了一下弱口令 sqlmap 都没跑出来 那么利用点应该不在这 考虑到之前有过dirsearch字典太小扫不到东西的经历 换个gobuster扫一下 先看看g…...

CentOS 虚拟机磁盘扩容(非常实用)

新手村的选手在刚开始安装使用 CentOS 虚拟机时&#xff0c;很多选项都会按照推荐操作来&#xff0c;比如&#xff1a;磁盘推荐大小为 20 GB&#xff1b;但随着后面的使用&#xff0c;总会因为“磁盘根目录不足”原因&#xff0c;而导致软件无法安装、虚拟机无法正常运行等&…...

docker案例复现

$uri导致的CRLF注入漏洞 前期准备dockerdocker compose 漏洞配置 前期准备 docker 要完成这样的测试&#xff0c;需要我们有一定的环境&#xff0c;也就是需要大家去安装docker 更新系统软件包&#xff1a; sudo yum update 安装 Docker 的依赖软件包&#xff1a; sudo yum …...

淘宝资源采集(从零开始学习淘宝数据爬取)

1. 为什么要进行淘宝数据爬取&#xff1f; 淘宝数据爬取是指通过自动化程序从淘宝网站上获取数据的过程。这些数据可以包括商品信息、销售数据、评论等等。淘宝数据爬取可以帮助您了解市场趋势、优化您的产品选择以及提高销售额。 淘宝作为全球的电商平台&#xff0c;每天都有…...

【C语言】预处理详解

本文目录 1 预定义符号 2 #define 2.1 #define 定义标识符 2.2 #define 定义宏 2.3 #define 替换规则 2.4 #和## 2.5 带副作用的宏参数 2.6 宏和函数对比 2.7 命名约定 3 #undef 4 命令行定义 5 条件编译 6 文件包含 6.1 头文件被包含的方式 6.2 嵌套文件包含 1 预定义符号 __…...

2023中国(合肥)场景创新峰会成功举办,全息网御被纳入《合肥市第二批场景能力清单》

场景作为重要的城市资源&#xff0c;在驱动科技创新、产业发展、城市治理方面发挥着重要作用。近年来&#xff0c;为促进数字技术与实体经济深度融合&#xff0c;加速前沿科技转化落地、吸引全球创新资源集聚&#xff0c;合肥市聚焦“双找”&#xff1a;为产品找场景&#xff0…...

QT QLCDNumber 使用详解

本文详细的介绍了QLCDNumber控件的各种操作&#xff0c;例如&#xff1a;新建界面、源文件、设置显示位数、设置进制、设置外观、设置小数点、设置溢出、显示事件、其它文章等等操作。 实际开发中&#xff0c;一个界面上可能包含十几个控件&#xff0c;手动调整它们的位置既费时…...

明年,HarmonyOS不再兼容Android应用!

2023年华为开发者大会&#xff0c;不知道各位老铁们是否观看了&#xff0c;一个震撼的消息就是&#xff0c;首次公开了HarmonyOS NEXT的概念&#xff0c;简而言之就是&#xff0c;这是一款专为开发者打造的预览版操作系统&#xff0c;旨在提供"纯正鸿蒙操作系统"的体…...

华为OD机试 - 人气最高的店铺(Java JS Python)

题目描述 某购物城有m个商铺,现决定举办一场活动选出人气最高店铺。 活动共有n位市民参与,每位市民只能投一票,但1号店铺如果给该市民发放 q 元的购物补贴,该市民会改为投1号店铺。 请计算1号店铺需要最少发放多少元购物补贴才能成为人气最高店铺(即获得的票数要大于其…...

mysql sql 语句sum求和嵌套数学表达式

今天有个需求, 已减高度 高度 x 单双开(单开1 双开2) x 2,要直接写在sql语句中。 表字段 包含 高度 和 单双开字段 值是字符串 (双开 左单开 右单开) -- 已减高度 2 * 单双开 * 高度 sum( -- 求和 表达式 已减高度 2 * 单双开 * 高度 t_cloth.hegiht * 2 * (case WHEN l…...

Java课题笔记~ Servlet编程

1.Servlet编程基础 (1)什么是Servlet Servlet是基于Java语言的Web编程技术&#xff0c;部署在服务器端的Web容器里&#xff0c;获取客户端的访问请求&#xff0c;并根据请求生成响应信息返回给客户端。 创建Servlet的方式&#xff0c;有 如下图&#xff1a;一般创建Servlet都…...

修改IDEA的idea.vmoptions参数导致IDEA无法打开(ReservedCodeCacheSize)

事发原因 Maven导依赖的时候OOM&#xff0c;因此怀疑是内存太小&#xff0c;尝试修改idea.vmoptions的参数&#xff0c;然后发现IDEA重启后打不开了&#xff0c;卸载重装后也无法打开。。。 实际上如果导包爆出OOM的话应该调整下图参数&#xff0c;不过这都是后话了 解决思路…...

P1321 单词覆盖还原

题目描述 一个长度为 l l l 的字符串中被反复贴有 boy 和 girl 两单词&#xff0c;后贴上的可能覆盖已贴上的单词&#xff08;没有被覆盖的用句点表示&#xff09;&#xff0c;最终每个单词至少有一个字符没有被覆盖。问贴有几个 boy 几个 girl&#xff1f; 输入格式 一行被…...

GODOT游戏引擎简介,包含与unity性能对比测试,以及选型建议

GODOT&#xff0c;是一个免费开源的3D引擎。本文以unity作对比&#xff0c;简述两者区别和选型建议。由于是很久以前写的ppt&#xff0c;技术原因视频和部分章节丢失了。建议当做业务参考。 GODOT目前为止遇到3个比较重大的基于&#xff0c;第一个是oprea的合作奖&#xff0c;…...

Add-in Express for Microsoft Office and Delphi Crack

Add-in Express for Microsoft Office and Delphi Crack 适用于Microsoft Office和Delphi VCL的Add-in Express使您能够在几次点击中为Microsoft Office开发专业插件。它生成基于COM的项目&#xff0c;这些项目包含Microsoft Office外接程序或智能标记的所有必要功能&#xff0…...

opencv基础-34 图像平滑处理-2D 卷积 cv2.filter2D()

2D卷积是一种图像处理和计算机视觉中常用的操作&#xff0c;用于在图像上应用滤波器或卷积核&#xff0c;从而对图像进行特征提取、平滑处理或边缘检测等操作。 在2D卷积中&#xff0c;图像和卷积核都是二维的矩阵或数组。卷积操作将卷积核在图像上滑动&#xff0c;对每个局部区…...

webSocket 与传统的 http 有什么优势

webSocket 与传统的 http 有什么优势 当页面中需要观察实时数据的变化&#xff08;比如聊天、k 线图&#xff09;时&#xff0c;过去我们往往使用两种方式完成 第一种是短轮询&#xff0c;即客户端每隔一段时间就向服务器发送消息&#xff0c;询问有没有新的数据 第二种是长轮询…...

如何测试Linux磁盘的读写速度

在Linux系统中也有很多命令可以测试硬盘的读写速度指标。以下是几个常用命令&#xff08;注意&#xff1a;在执行测试命令之前&#xff0c;请务必备份数据以避免数据丢失&#xff01; 1、dd 命令 首先挂载磁盘 mount /dev/sdb /testdd 命令可用于进行硬盘读写速度测试。 例…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...