数据结构之初始泛型
找往期文章包括但不限于本期文章中不懂的知识点:
个人主页:我要学编程(ಥ_ಥ)-CSDN博客
所属专栏:数据结构(Java版)
目录
深入了解包装类
包装类的由来
装箱与拆箱
面试题
泛型
泛型的语法与使用
泛型如何编译的
泛型的上界
泛型方法
泛型占位符
深入了解包装类
我们在最开始学习Java的数据类型时,就知道了Java的八大基本数据类型有自己对应的包装类,也就是引用类型。今天,我们就来彻底了解它们。
包装类的由来
在Java中,由于基本类型不是继承自Object类,为了在泛型代码中可以支持基本类型,Java给每个基本类型都创造了对应的一个包装类型。如下:
基本数据类型 | 包装类 类型 |
byte | Byte |
char | Character |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
装箱与拆箱
装箱也叫作:装包。就是把基本数据类型转换成其对应的包装类 类型。
例如:
public class Test {public static void main(String[] args) {Integer a = 10;Integer c = new Integer(10);Integer b = Integer.valueOf(10);System.out.println(a);System.out.println(b);System.out.println(c);}
}
上面三种写法,都是装箱的操作,即把基本数据类型转换成其对应的包装类 类型。但要注意的是第二种方法,虽然代码可以正常执行,但我们现在不再使用这种方法了。从Java 9开始,这个方法就已经被摒弃了。下面是Java 8 和 Java 17的不同情况:
Java 8:
Java 17:
需要注意的是:这里爆红,但还是可以运行通过的。
拆箱也叫作:拆包。就是把包装类 类型转换成其对应的基本数据类型。
例如:
public class Test {public static void main(String[] args) {Integer integer = 10;int a = integer;int b = integer.intValue();System.out.println(a);System.out.println(b);}
}
注意:
当我们显式地去调用方法来进行装箱或者拆箱操作时,这种方式叫做:显式装箱(拆箱)。
当我们直接把基本数据类型转换为其对应的包装类 类型或者进行这种拆箱操作时,这就叫做:自动装箱(拆箱)。
public class Test {public static void main(String[] args) {Integer a = 10; // 自动装箱Integer b = Integer.valueOf(10); // 显式装箱int c = a; // 自动拆箱int d = b.intValue(); // 显式拆箱}
}
面试题
public class Test {public static void main(String[] args) {Integer a = 100;Integer b = 100;System.out.println(a == b); // 结果是 trueInteger c = 200;Integer d = 200;System.out.println(c == d); // 结果是 false}
}
这里同样都是自动装箱,为什么输出的结果会不一样呢?
分析:a b c d 在这里都是一个引用类型,那么在用 == 比较时,比较的是它们各自在堆区的地址。这也就说明 a 和 b在堆区是同一块地址,但是c 和 d 在堆区不是同一块地址。
我们就可以去看这个装箱的源码,看看到底做了什么?
可以看到当装箱的 i 的值在 [low, high] 之间的时候,返回的是一个数组所对应的下标的值,而当 i 不在这个范围内时,返回的是一个新的对象。因此,我们可以得出结论了:100在这个范围内,200不在这个范围内。我们还是可以看一个这个源码对应的 low 和 high 的值的。
low 对应的值是 -128,high 对应的值是 127。
根据条件得出这个数组大致是这样的。因此 当 i = 100时,返回的是在数组中的同一份;而 i = 200时,返回的是 new 的一个新对象。
泛型
包装类的出现就是为泛型服务的。那么什么是泛型呢?顾名思义:就是一个广泛的类型。泛型的出现是为了解决掉:一个类或者方法只能解决对应类型的问题。
例如:对整型数据排序,就只能用整型数组类解决。
class Myarray {public static void bubble_sort (int[] array) {// 趟数for (int i = 0; i < array.length; i++) {boolean flag = true;// 每一趟要比较的内容for (int j = 0; j < array.length-i-1; j++) {if (array[j] > array[j+1]) {int tmp = array[j];array[j] = array[j+1];array[j+1] = tmp;flag = false;}}if (flag) {break;}}}
}
public class Test {public static void main(String[] args) {int[] array = {10,9,8,7,6,5,4,3,2,1};System.out.println("排序前:"+ Arrays.toString(array));Myarray.bubble_sort(array);System.out.println("排序后:"+ Arrays.toString(array));}
}
从排序的结果来看:这个排序的功能是正确的。但是也只局限于排序整型数据,不能排序其他类型的数据,如果要排序的话,还得重新写一个这样的方法。于是就出现了泛型。 所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。
泛型的语法与使用
class 泛型类名称<类型形参列表> {// 这里可以使用类型参数
}
这里的参数列表可以不只有一种。就像下面这样:
class 泛型类名称<T1,T2,....,Tn> {}
这里的T代表的是占位符,表示当前类是一个泛型类。
类型形参一般使用一个大写字母表示,常用的名称有:
E 表示 Elements K 表示 Key V 表示 Value
N 表示 Number T 表示 Type S, U, V 等等 - 第二、第三、第四个类型
至于这些占位符的区别以及各自之间的含义,我们待会再学习。我们可以用一个数组来接收多种不同的元素了。
class MyArray<T> {// 语法规定不能创建泛型数组,但Object可以拥有接收所有类的功能public Object[] objects;public MyArray(){this.objects = new Object[10];}public T getValue(int pos) {// 取出来的是一个Object类,得强转成 Treturn (T)objects[pos];}public void setValue(int pos, T value) {// 这里不考虑pos的无效,注重这里的思想objects[pos] = value;}
}public class Test {public static void main(String[] args) {MyArray<Integer> myarray = new MyArray<>();myarray.setValue(0, 10);myarray.setValue(1, 20);// 这里可写可不写MyArray<String> myArray = new MyArray<String>();myArray.setValue(0, "Hello");myArray.setValue(1, "World");}
}
这里就实现了同一个类,但是可以接收不同的类型,实现了类型的参数化。这就是泛型的意义。
注意:
1. 泛型只能接受类,所有的基本数据类型必须使用包装类!
2. 编译器会根据我们在实例化一个对象的时候来判断这个T到底是什么类型。
3. 我们也可能会遇到有的代码在使用泛型类时,没有标明具体的类型,但是还是可以运行通过。这是因为泛型这个概念是在 java 5之后提出来的。之前的 java 版本并没有这种写法,所以为了兼容老版本,泛型类在实例化时,会有未标明具体类型的情况,这种叫做裸类型。但是我们最好不要写这种代码出来。
泛型如何编译的
泛型是只存在于编译时期的名词,因为在编译过后不存在T、E等泛型占位符了。泛型的占位符在编译之后就被替换成了Object。这种机制被称为“擦除机制” 。将占位符擦除成Object。
泛型的上界
如果我们想要限制泛型的传过来的种类也是可以的。
在定义泛型类时,有时需要对传入的类型变量做一定的约束(就像上面那样),可以通过类型边界来约束。
语法:
class 泛型类名称<类型形参 extends 类型边界> {...
}
注意:其实所有的泛型类都有一个上界:Object。
泛型方法
语法:
方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) {...
}
例如:
// 规定这个方法是叫把pos位置的值置为value
public static <T> void swap (T[] array, int pos, T value) {array[pos] = value;
}
注意:只有静态的泛型方法里面才能有泛型的出现,普通的静态方法不能有泛型的出现。
这句话不是说只有静态方法才能是泛型方法,普通方法也可以是泛型方法。只是说不是泛型的方法里面如果没有实例化泛型对象,就不能出现任何与泛型有关的东西。
因此,上面的排序就可以用泛型方法来解决。但是会有一个新的问题:Comparable 与 这个数组会出现不兼容的情况,因为这个数组是基本数据类型,没有实现接口这一说法。所以得把这个数组变成包装类,但是在传参的过程中,T会被擦除成Object类,因此即使我们传过去的参数强转成T[ ],也会发生类型转换异常。
因此这个排序最终是失败了。所以我就没有把代码传上来。但是泛型还是有很大的好处的:可以让一份代码对不同的对象执行相同的操作。
类型推导
class Myarray<T> {// ......
}public class Test {public static void main(String[] args) {// 通过这个 Integer 来推导出 Myarray 中的泛型Myarray<Integer> myarray = new Myarray<>();}
}
上面是泛型类的推导。下面是泛型方法的推导
class Myarray {public <T> void func () {// ......}
}public class Test {public static void main(String[] args) {Myarray myarray = new Myarray();// 通过这个 Integer 来推断这个 T(也可以不写,编译器会根据其具体操作来判断)myarray.<Integer>func();}
}
泛型占位符
接下来就学习泛型占位符的知识:
在Java泛型中,像 <T> 和 <E> 这样的占位符是用来表示类型参数的。它们本身没有本质上的区别,都代表一种未知的类型,将在编译时期由具体的实际类型替换。选择使用T、E或其他的,更多是基于习惯和上下文的清晰性。以下是几个常用的占位符及其常见用途:
T - 通常代表 Type,是最常见的泛型占位符,用于表示任何类型。在没有特定上下文暗示的情况下,泛型类或方法常使用
T
。E - 通常代表 Element,特别在集合框架中使用较多,暗示它代表集合中的元素类型,如 List<E> 或 set<E>。
K - 代表 Key,通常用在表示键的类型,比如在 Map <K,V> 中。
V - 代表 Value,通常与 K 一起使用,表示映射中的值类型。
N - 有时代表 Number,表示数值类型,尽管这不是Java标准库中的正式约定,但在特定上下文中可能会看到它的使用。
使用这些占位符主要是为了提高代码的可读性和自文档化能力。开发者可以根据上下文选择最合适的占位符来表达意图,但最终这些占位符都会被编译器替换为具体的类型信息,不会影响到生成的字节码或运行时行为。
此外,泛型中还有一个特殊的占位符 ?(问号),它作为通配符使用,表示未知的类型,可以有三种形式:无界通配符(?)、上界通配符(
? extends SomeType
)和下界通配符(? super SomeType
),用来实现更灵活的泛型参数约束。(了解即可)
这里基本就是java泛型语法的全部内容啦!通过对泛型的学习,我们就可以让代码变得更加高大上一些。
好啦!本期 数据结构之初始泛型 的学习之旅就到此结束了!相信通过这篇文章的学习,你对Java中泛型的了解将会更进一步!我们下一期再一起学习吧!
相关文章:
数据结构之初始泛型
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构(Java版) 目录 深入了解包装类 包装类的由来 装箱与拆箱 面试题 泛型 泛型的语法与使用…...
【网络编程开发】7.TCP可靠传输的原理
7.TCP可靠传输的原理 TCP实现可靠传输的原理主要基于序列号和确认应答、超时重传、滑动窗口、连接管理机制以及拥塞控制等多重机制。 TCP(Transmission Control Protocol),即传输控制协议,是网络通信中的一种重要协议࿰…...
视觉SLAM十四讲:从理论到实践(Chapter8:视觉里程计2)
前言 学习笔记,仅供学习,不做商用,如有侵权,联系我删除即可 一、目标 1.理解光流法跟踪特征点的原理。 2.理解直接法是如何估计相机位姿的。 3.实现多层直接法的计算。 特征点法存在缺陷: 二、光流(Optical Flow) …...
C语言过度C++语法补充(面向对象之前语法)
目录 1. C相较于C语言新增的语法 0. C 中的输入输出 1. 命名空间 1. 我们如何定义一个命名空间? 2. 如何使用一个命名空间 3. 命名空间中可以定义什么? 4. 在 相同或者不同 的文件中如果出现 同名的命名空间 会如何? 5. 总结~~撒花~~…...
类和对象(二)(C++)
初始化列表 class Date{public:Date(int year, int month, int day){_year year;_month month;_day day;}private:int _year;int _month;int _day;}; 虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化…...
Chrome DevTools解密:成为前端调试大师的终极攻略
Chrome DevTools是一套内置于Google Chrome浏览器中的开发者工具,它允许开发者对网页进行调试、分析和优化。本文将全面介绍DevTools的功能、使用方法以及注意事项,帮助开发者更好地利用这些工具来提升开发效率和网页性能。 一、简介 1. DevTools是什么…...
【python】OpenCV—Cartoonify and Portray
参考来自 使用PythonOpenCV将照片变成卡通照片 文章目录 1 卡通化codecv2.medianBlurcv2.adaptiveThresholdcv2.kmeanscv2.bilateralFilter 2 肖像画cv2.divide 1 卡通化 code import cv2 import numpy as npdef edge_mask(img, line_size, blur_value):gray cv2.cvtColor(…...
制作AI问答机器人:从0到1的完整指南
在数字化转型的浪潮中,企业正追求更高效、智能的客户服务解决方案。AI问答机器人以其快速响应、全天候服务和持续学习的能力,成为了提升客户满意度和加速业务发展的关键工具。本文将深入探讨如何制作一个企业级的AI问答机器人,并强调其功能体…...
mysql 数据库datetime 类型,转换为DO里面的long类型后,只剩下年了,没有了月和日
解决方法也简单: 自定义个一个 Date2LongTypeHandler <resultMap id"BeanResult" type"XXXX.XXXXDO"><result column"gmt_create" property"gmtCreate" jdbcType"DATE" javaType"java.lang.Long&…...
信息系统项目管理师0148:输出(9项目范围管理—9.3规划范围管理—9.3.3输出)
点击查看专栏目录 文章目录 9.3.3 输出 9.3.3 输出 范围管理计划 范围管理计划是项目管理计划的组成部分,描述将如何定义、制定、监督、控制和确认项 目范围。范围管理计划用于指导如下过程和相关工作: ①制定项目范围说明书;②根据详细项目范…...
解决 SQLyog 连接 MySQL 8 连不上和 SQLyog Trial 试用到期的问题
今天发现 SQLyog 突然连不上 MySQL 了,跟之前不一样的地方就是我升级了 MySQL,升级到了 MySQL 8。 原来是因为 MySQL 8 引入了新的密码验证机制。在 MySQL 8 中默认的密码验证插件从 mysql_native_password 更换为 caching_sha2_password。我的 SQLYog …...
go语言内置预编译 //go:embed xxx 使用详解
在go语言里面,我们可以使用一个“类注释”的语法来来让编译器帮助我们在编译的时候将一些文件或者目录读取到指定的变量中来供我们使用。 go:embed语法: //go:embed 文件或者目录路径 var 变量名 变量类型 说明: 文件或者目录路径 可以…...
数据挖掘--挖掘频繁模式、关联和相关性:基本概念和方法
频繁项集、闭项集和关联规则 频繁项集:出现的次数超过最小支持度计数阈值 闭频繁项集:一个集合他的超集(包含这个集合的集合)在数据库里面的数量和这个集合在这个数据库里面的数量不一样,这个集合就是闭项集 如果这个集合还是频繁的,那么他就是极大频…...
Locust:用Python编写可扩展的负载测试
Locust:简化性能测试,让负载模拟更直观- 精选真开源,释放新价值。 概览 Locust是一个开源的性能和负载测试工具,专门用于HTTP和其他协议的测试。它采用开发者友好的方法,允许用户使用普通的Python代码来定义测试场景。…...
【Neo4j】Windows11使用Neo4j导入CSV数据可视化知识图谱
Windows11使用Neo4j导入CSV数据可视化知识图谱 序1. 安装JDK21(1)下载(2)安装(3)环境配置 2. 安装Neo4j(1)下载(2)解压安装(3)环境配置…...
探索智慧林业系统的总体架构与应用
背景: 随着人们对森林资源保护和管理的重视,智慧林业系统作为一种新兴的林业管理手段,正在逐渐受到广泛关注和应用。智慧林业系统的总体架构设计与应用,将现代信息技术与林业管理相结合,为森林资源的保护、管理和利用…...
【JSP】如何在IDEA上部署JSP WEB开发项目
以我的课设为例,教大家拿到他人的项目后,如何在IDEA上部署。 需要准备: JDK17(或者JDK13)IntelliJ IDEA 2023.2.6MySQL 8.0Tomcat 9.0 一,新建项目添加文件 1.1复制“位置”的路径 1.2找到该文件夹 1.3…...
用HTML实现拓扑面,动态4D圆环面,可手动调节,富有创新性的案例。(有源代码)
文章目录 前言一、示例二、目录结构三、index.html(主页面)四、main.js五、Tour4D.js六、swissgl.js七、dat.gui.min.js八、style.css 前言 如果你觉得对代码进行复制粘贴很麻烦的话,你可以直接将资源下载到本地。无需部署,直接可…...
java调用GDAL及JTS实现生成泰森多边形(Voronoi图)的一种方法
目录 一、关于泰森多边形 1.泰森多边形的特性 2.本文的目的 二、实现思路 1.gdal和jts库的maven坐标 2.jts生成泰森多边形的关键代码 3.使用GDAL读取源文件信息的关键代码 4.使用GDAL将生成的泰森多边形写入文件 三、实现结果 1.实现的效果 2.完整代码示例 一、关于…...
Type-C音频转接器方案
在数字化时代,音频设备作为我们生活中不可或缺的一部分,其连接方式的便捷性和高效性显得尤为重要。Type-C音频转接器,作为一种新型的音频连接解决方案,正逐渐走进我们的生活,以其独特的优势改变着我们的音频体验。 一、…...
linux 服务器上离线安装 node nvm
因为是离线环境 如果你是可以访问外网的 下面内容仅供参考 也可以继续按步骤来 node 安装路径 Node.js — Download Node.js nvm 安装路径 Tags nvm-sh/nvm GitHub 后来发现 nvm安装后 nvm use 版本号 报错 让我去nvm install 版本 我是内网环境 install不了 下面 你要 把安…...
Web前端三大主流框架:React、Angular和Vue的比较与选择
Web前端三大主流框架:React、Angular和Vue的比较与选择 Web前端技术的快速发展为开发者提供了丰富的工具和框架,其中React、Angular和Vue是当前最受欢迎的三大框架。这三个框架各有特点,适用于不同的项目需求和开发团队。本文将对React、Ang…...
C# MemoryCache 缓存应用
摘要 缓存是一种非常常见的性能优化技术,在开发过程中经常会用到。.NET提供了内置的内存缓存类 MemoryCache,它可以很方便地存储数据并在后续的请求中快速读取,从而提高应用程序的响应速度。 正文 通过使用 Microsoft.Extensions.Caching.Me…...
【学习笔记】Linux前置准备
视频学习资料 基础: 黑马0基础(前面四章即可,包含软件基础安装配置) 进阶: 黑马程序员-Linux系统编程 黑马程序员-Linux网络编程 我也还没看,看了眼目录感觉把八股里面很多场景都讲到了,感觉有…...
各种空气能热泵安装图
空气能热泵安装图 循环式空气能热泵安装图 直热循环式空气能热泵安装图 泳池空气能热泵安装图 循环式水源热泵热安装系统原理图 直热循环式水源热泵安装系统图 空气水源热泵安装图...
软件杯 题目:基于深度学习的中文对话问答机器人
文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分:4.2 损失函数:4.3 搭建seq2seq框架:4.4 测试部分:4.5 评价NLP测试效果:4.6 梯度截断…...
UI学习笔记(一)
UI学习 一:UIView基础frame属性隐藏视图对象:UIView的层级关系 二:UIWindow对象三:UIViewController基础UIViewController使用 四:定时器与视图移动五:UISwitch控件六:滑动条和进度条七…...
【C语言训练题库】扫雷->简单小游戏!
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 题目 2. 解析 3. 代码 4. 小结 1. 题目 小sun上课的时候非常喜欢玩扫雷。他现小sun有一个初始的雷矩阵,他希望你帮他生成一个扫雷矩阵。 扫雷…...
WMS仓储管理系统高效驱动制造企业物料管理
在现代制造业的快速发展中,仓储管理作为供应链的核心环节,其效率直接影响到企业的生产力和市场竞争力。随着科技的进步,实施WMS仓储管理系统逐渐成为推动仓储管理向智能化转型的关键力量。本文将深入探讨WMS仓储管理系统如何以创新的方式驱动…...
python使用appium打开程序后,为什么没有操作后程序就自动退出了
当使用Appium打开应用程序并在没有执行任何操作后它自动退出,这可能是由于几个不同的原因。以下是一些可能的原因和相应的解决方案: 应用程序的默认行为: 有些应用程序在启动后如果没有用户交互,可能会因为超时或其他逻辑而自动关…...
太阳能 技术支持 东莞网站建设/如何优化网站快速排名
梦晨 明敏 发自 凹非寺量子位 | 公众号 QbitAI一觉醒来,机器学习社区炸了锅。因为最新研究发现,只要对GPT-3说一句“让我们一步一步地思考”,就能让它正确回答出以前不会的问题。比如下面这个例子:16个球中有一半是高尔夫球&#…...
网站登录 退出怎么做/淘宝竞价排名
方法一:设置环境变量 PGPASSWORD PGPASSWORD 是 PostgreSQL 系统环境变量,连接远端数据库时,将优先使用这个密码。变量是临时的,在关闭 shell 时失效。具体步骤是:先设置环境变量,备份,再删…...
专门做国外家具书籍的网站/百度网站排名优化
育软件、程序设计软件、网络软件、工具软件。(三)Word文字处理【教学目的与要求】1、通过本部分的学习,了解Word窗口的组成部分;了解在Word中插入与编辑公式的方法;2、理解Word文字排版中的常见概念;理解word中表格的行、列、单元…...
静态页面改wordpress/百度下载免费安装到桌面
函数 要用到QListWidget类的setItemWidget()函数,其原型如下: void QListWidget::setItemWidget(QListWidgetItem * item, QWidget * widget) 释义 形参第二项中可以将QCheckBox类型的指针强制转换为QWidget 类型。函数的实质是将小部件wi…...
金钟街网站建设哪家好/武汉seo顾问
图像处理中,有很多算法由于其内在的复杂性是天然的耗时大户,加之图像本身蕴涵的数据量比一般的对象就大,因此,针对这类算法,执行速度的提在很大程度上依赖于硬件的性能,现在流行的CPU都是至少2核的…...
丰台网站建设多少钱/seo站点
考研真题资料优惠价原价选择湖南科技大学(专业学位)计算机技术教材,也叫湖南科技大学(专业学位)计算机技术考研参考书、指定书目等等,是考验专业课复习过程中最重要的资料。考研是一种针对性很强的考试项目,参考书目由报考院校的研究生院制定…...