【java基础】泛型程序设计基础
文章目录
- 泛型是什么
- 自定义泛型类
- 自定义泛型方法
- 类型变量的限定
- 总结
泛型是什么
泛型类和泛型方法有类型参数,这使得它们可以准确地描述用特定类型实例化时会发生什么。在没有泛型类之前,程序员必须使用Objct编写适用于多种类型的代码。这很烦琐,也很不安全。
随着泛型的引入,Java有了一个表述能力很强的类型系统,允许设计者详细地描述变量和方法的类型要如何变化。
泛型程序设计(generic programming)意味着编写的代码可以对多种不同类型的对象重用。
下面的代码就是没有使用泛型的集合
// 该集合我想要存放int类型的数据List list = new ArrayList();list.add(100); // 加入intlist.add("hello"); // 放入字符串list.add(true); // 放入布尔类型for (int i = 0; i < list.size(); i++) {Object o = list.get(i); // 获取到的值是Objectint k = (Integer) o; // 强制转换System.out.println(k);}
可以发现上面的代码在集合中什么都能放入,并没有进行类型检查。而且在获取集合元素的时候返回的是Object,我们还要进行强转。运行看看一下,结果如下

可以发现报错了,这就是因为在集合里面存放了其他类型的数据。集合不使用泛型那么就是存储的Object数据,我们将其转换为Integer所以就出现了ClassCastException。现在就已经可以发现java的弊端了,没有一个参数检查机制,代码极不安全,泛型就是用来弥补这点的。看下面泛型代码。
List<Integer> list = new ArrayList<>();list.add(100);// list.add("hello") // 类型检查,编译都不能通过// list.add(true) // 编译不能通过for (int i = 0; i < list.size(); i++) {Integer k = list.get(i); // 返回的直接就是IntegerSystem.out.println(k);}
我们可以在<>里面指定要存储的元素类型,这就是泛型,使用泛型后在往集合添加元素的时候就会进行检查,如果不是指定的元素,那么就会出现编译错误,程序编译都不能通过。使用泛型后,集合返回的就直接是指定的类型,也就不需要强转类型转换了。
通过上面的代码,大家应该初步体会到了泛型的好处和强大,下面就来学习如何自定义泛型类和泛型方法
自定义泛型类
泛型类就是有一个或多个类型变量的类。下面我就通过MyTool这个类来进行说明
public class MyTool<T> {private T info;public MyTool(T info) {this.info = info;}public T getInfo() {return info;}
}
上面的MyTool这个类就是一个泛型类,在这个类中引入了一个类型变量T,用尖括号(<>)括起来的,放在类名后面。这个T就是我们在创建对象的时候指定的。
MyTool<String> myTool = new MyTool<>("这是自定义泛型类");
我们在尖括号(<>)里面写的类型就会成为T的类型,这里<>里面写的类型为String,那么T就是代表String。
对于 new MyTool<>(“这是自定义泛型类”) 这部分代码,我们在构造器中传入了一个字符串,原因就是T代表的是字符串,而我们的构造器中要传入的内容就是T,也就是字符串,没有问题。
对于在上面的MyTool类,由于我们指定的T为String,所以可以将其理解为就是一个普通类,如下
public class MyTool {private String info;public MyTool(String info) {this.info = info;}public String getInfo() {return info;}
}
现在,对于泛型类的基本使用基本就说完了,我们自定义泛型类就是在类后面加上<>,在这里面写上类型变量,然后再类中使用这个类型变量即可。对于类型变量,我们一般都是使用大写字母,而且很简短,在Java库使用变量E表示集合的元素类型,K和V分别表示表的键和值的类型。T(必要时还可以用相邻的字母U和S)表示“任意类型”。
注意:对于类型变量并不是一定为一个大小字母,只不过是约定俗成罢了,例如,下面代码也是正确的
public class TypeParameter<AAAAA> {private AAAAA aaaaa;
}
但是还是建议大家就写为一个大写字母,遵顼java规范。
对于泛型类,我们在<>里面可以写上多个类型变量,使用逗号分隔,例如下面代码
public class MulTypeParam<K,V> {
}
这样定义以后,我们在使用这个对象就要在<>里面传入2个变量
MulTypeParam<Integer, String> typeParam = new MulTypeParam<>();
这样写的话,那么K就代表Integer类型,V就代表String类型
自定义泛型方法
上面说的是自定义泛型类,现在来讲一下泛型方法。下面就是一个简单示例
public class SimpleGenericMethod {public static <T> T getMiddleInfo(T... ts) {int index = ts.length / 2;return ts[index];}
}
对于泛型方法,我们并不需要放在泛型类中,放在普通类中也没有问题。对于泛型方法,我们将类型变量放在<>中,<>放在返回值前面,修饰符后面。
上面的方法就是接收T类型的参数,然后返回一个T。下面就是对泛型方法的调用
String middleInfo = SimpleGenericMethod.<String>getMiddleInfo("java", "python", "c", "c++", "php");
可以发现在泛型方法中,我们是在方法前面添加了一个<>,然后指定了类型。但是对于大多数情况下,<>都可以省略,编译器会根据传入的参数推断出类型。
在几乎所有情况下,泛型方法的类型推导都可以正常工作。下面写法就是省略<>写法
String middleInfo = SimpleGenericMethod.getMiddleInfo("java", "python", "c", "c++", "php");
类型推导的原则就是寻找参数的公共父类。
对于泛型方法,我们也可以在<>里面定义多个类型变量
public static <X, Y> Y towTypeParam(X x, Y y) {return y;}
上面代码就表示传入一个X类型的变量和一个Y类型的变量,然后返回一个Y类型变量。
类型变量的限定
在很多的情况下,我们使用泛型时,并不是上面类型的参数都能传入,而是有所现在,比如是某个类的子类,或者必须实现某个接口。下面就来说明如何完成这些对泛型的限制。
先来看一个例子
public interface Eat {void eat();
}
public class TypeParamRestrict {public static <T> void eats(T... ts) {for (T t : ts) {((Eat) t).eat();}}
}
看看上面这个eats有上面问题呢?可以发现,我们并没有检查T类型的参数,T不一定是一个实现接口的Eat的对象,这样调用就会出错,所以,我们应该对T进行限制,写法如下
public class TypeParamRestrict {public static <T extends Eat> void eats(T... ts) {for (T t : ts) {t.eat();}}
}
T extends Eat就表示传入的类型必须是为Eat,或者Eat的子类。这里使用extends可能有人很疑惑,Eat不是接口吗?为什么是使用extends,事实上,这里选择extends是为了更接近子类的概念,对于接口和类都是使用extends。使用了限定符后,就不需要进行类型转换了,T已经是Eat的子类,所以可以直接掉用eat方法。
上面这样写了以后,再调用eats这个方法,参数就必须是实现Eat接口的类。
对于一个类型变量,我们还可以有多个限定,例如下面代码
<T extends Eat & Serializable>
使用&就表示必须且的意思,表示T要同时实现Eat和Serializable接口。
注意:对于限定,可以有多个接口,但是只能有一个是类,而且必须写为第一个限定。为什么只能有一个限定类,因为java是单继承的。类型变量不可能同时实现多个类
总结
泛型程序设计(generic programming)就是意味着编写的代码可以对多种不同类型的对象重用。
关于泛型的更多知识,参考以下内容
泛型程序设计基础
类型擦除、桥方法、泛型代码和虚拟机
泛型的限制及其继承规则
泛型的通配符(extends,super,?)
相关文章:
【java基础】泛型程序设计基础
文章目录泛型是什么自定义泛型类自定义泛型方法类型变量的限定总结泛型是什么 泛型类和泛型方法有类型参数,这使得它们可以准确地描述用特定类型实例化时会发生什么。在没有泛型类之前,程序员必须使用Objct编写适用于多种类型的代码。这很烦琐ÿ…...
【省选模拟测试23 T1直径】更好的做法
题目大意和普通做法 省选模拟测试23 T1直径 题解 对于上文中有三个儿子的根节点的树,其直径数量为abbccaabbccaabbcca。那么对于上文中有nnn个儿子的根节点的树,其直径数量为多少呢? 每个儿子所在子树中的点与其他儿子所在子树中的点都能组…...
SpringCloud基础(3)-微服务远程调用
SpringCloud基础1. 微服务的远程调用2. Eureka注册中心1. 搭建Eureka服务注册中心1. 微服务的远程调用 服务提供者:一次业务中被其它服务调用的一方; 服务消费者:一次业务中调用其它服务的一方; 2. Eureka注册中心 记录所有服务…...
10.单点登录原理及JWT实现
单点登录原理及JWT实现 一、单点登录效果 首先我们看通过一个具体的案例来加深对单点登录的理解。案例地址:https://gitee.com/xuxueli0323/xxl-sso?_fromgitee_search 把案例代码直接导入到IDEA中 然后分别修改下server和samples中的配置信息 在host文件中配置 …...
图表控件LightningChart.NET 系列教程(十一):LightningChart 组件——添加至 Blend WPF 项目
LightningChart.NET 是一款高性能 WPF 和 Winforms 图表,可以实时可视化多达1万亿个数据点。可有效利用CPU和内存资源,实时监控数据流。同时,LightningChart使用突破性创新技术,以实时优化为前提,大大提升了实时渲染的效率和效果&…...
libGDX:灯光效果实现一(实现一个点光源)
国内的libGDX文章很少,特别是libGDX实现灯光效果,所以就开始总结灯光效果的实现 绿色的框 是为了方便看到Body位置,使用Box2DDebugRenderer渲染的 工欲善其事,必先利其器,工具集合 gdx-setup.jar 1. 从libGDX官网下载…...
Java生态/Redis中如何使用Lua脚本
文章目录一、安装LUA1)简单使用二、lua语法简介1、注释1)单行注释2)多行注释2、关键字3、变量1)全局变量2)局部变量4、数据类型1)Lua数组2)字符串操作5、if-else6、循环1)for循环1&g…...
网络编程 socket 编程(一)
1. C/S 架构 C/S 架构即客户端/服务端架构,B/S 架构(浏览器与服务端)也是 C/S 架构的一种。 C/S 架构与 socket 的关系:学习 socket 可以完成 C/S 架构的开发。 2. osi 七层 一个完整的计算机系统由硬件、操作系统以及应用软件…...
【SpringCloud】SpringCloud教程之Nacos实战(一)
目录Nacos是什么?一.Nacos下载二.安装Nacos三.Nacos原理四.Nacos快速入门五.Nacos服务多级存储模式六.Nacos根据集群设置负载均衡1.根据同集群优先访问2.根据权重配置负载均衡七.Nacos的环境隔离八.Nacos和Eureka的区别前提:以订单服务和用户服务为例&am…...
高通Android 12/13 默认应用程序授予权限
1、一提到权限很多Android开发者都会想到 比如拨打电话 读取手机通讯录 定位 这些都是需要申请权限,Google Android 6.0之后(sdk 23) 需要app动态申请权限 或者权限组 2、我这里打个比方 比如需要在fm应用 默认打开mic权限 3、我们需要知道…...
代码随想录|day6|哈希表篇-- 242.有效的字母异位词 、349. 两个数组的交集 、202. 快乐数、1. 两数之和
总链接https://docs.qq.com/doc/DUEtFSGdreWRuR2p4?u329948d2f0044f34b7cbe72503f0b572 242.有效的字母异位词 链接:代码随想录 class Solution { public:bool isAnagram(string s, string t) {//两种做法,一种是int f[26]的数组,一种是map /*第一种&a…...
k8s学习之路 | Day20 k8s 工作负载 Deployment(下)
文章目录3. HPA 动态扩缩容3.1 HPA3.2 安装 metrics-server3.3 验证指标收集3.4 扩缩容的实现3.5 增加负载3.6 降低负载3.7 更多的度量指标4. 金丝雀部署4.1 蓝绿部署4.2 金丝雀部署4.3 金丝雀部署的实现5. Deployment 状态与排查5.1 进行中的 Deployment5.2 完成的 Deployment…...
考研复试——操作系统
文章目录操作系统1. 操作系统的特征:2. 进程与线程的关系以及区别3. 简述进程和程序的区别4. 进程的常见状态?以及各种状态之间的转换条件?5. 进程的调度算法有哪些?6. 什么是死锁?产生条件?如何避免死锁&a…...
Java ~ Collection/Executor ~ LinkedBlockingDeque【源码】
一 LinkedBlockingDeque(链接阻塞双端队列)类源码及机制详解 类 LinkedBlockingDeque(链接阻塞双端队列)类(下文简称链接阻塞双端队列)是BlockingDeqeue(阻塞双端队列)接口的唯一实现…...
【前缀和】截断数组、K倍区间、激光炸弹
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…...
函数编程:强大的 Stream API
函数编程:强大的 Stream API 每博一文案 只要有人的地方,世界就不会是冰冷的,我们可以平凡,但绝对不可以平庸。—————— 《平凡的世界》人活着,就得随时准备经受磨难。他已经看过一些书,知道不论是普通…...
企业架构图之业务架构图
在TOGAF的世界里面,所有的架构思想都可以通过下面三种类型的图形进行表示。 目录(Catalogs)矩阵(Matrix)图 (Diagram) 其架构图的本质就是用来进行沟通交流,通过架构图和业务团队进…...
监控易网络管理:网络流量分析
1、什么是网络流量分析2、网络流量分析的作用3、为什么要用网络流量分析功能,如何开启什么是网络流量分析简单的来说,网络流量分析就是捕捉网络中流动的数据包,并通过查看包内部数据以及进行相关的协议、流量、分析、统计等,协助发…...
RHCSA-文件内容显示(3.6)
查看命令 cat:显示文件内容 cat -n:显示文件内容的同时显示编号 tac:倒叙查看 head 文件名 (默认显示前10行):显示前10行 tail:显示末尾行数信息 more:查看文件信息,从头…...
Qt多线程文件查找器
⭐️我叫恒心,一名喜欢书写博客的研究生在读生。 原创不易~转载麻烦注明出处,并告知作者,谢谢!!! 这是一篇近期会不断更新的博客欧~~~ 有什么问题的小伙伴 欢迎留言提问欧。 Qt多线程文件查找器 前言 最近在实现一些代码功能的时候,需要找一些多线程样例来学习,于是就…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
