Java 基础(1)—泛型简单使用
一、泛型定义及作用
泛型是一种编程机制,允许在编写代码时使用参数化类型,以在编译时实现类型安全。 以下是泛型作用:
-
增强代码可读性和可维护性:通过在代码中使用泛型参数,可以使代码更清晰、更具有可读性和可维护性。
-
提高代码安全性:泛型可以在编译时检查类型,从而防止在运行时出现类型转换错误。
-
增加代码重用性:泛型允许在不同的数据类型上编写通用代码,从而提高代码的重用性。
-
简化代码:使用泛型可以避免重复编写类似的代码,从而简化代码。
总之,泛型是一种强大的编程机制,它可以帮助开发者编写更具可读性、可维护性、安全性和重用性的代码。
Java 泛型在编译期间会执行类型擦除(Type Erasure)。类型擦除是指编译器在编译泛型代码时,会将泛型类型擦除为其原始类型或限定类型,从而在运行时不存在泛型类型。在进行类型擦除时,编译器会将泛型类型参数替换为它们的边界(限定)类型(如果有的话),如果没有指定限定类型,则会将泛型类型参数替换为 Object 类型
例如,一个泛型类定义如下:
public class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}
在编译后,类型擦除会将泛型类型 T 擦除为 Object 类型,生成的字节码如下:
public class Box {private Object content;public void setContent(Object content) {this.content = content;}public Object getContent() {return content;}
}
需要注意的是,尽管在运行时不存在泛型类型,但是在编译期间编译器仍会对泛型类型进行类型检查,从而确保类型安全。
二、泛型使用
1、泛型定义在类上
代码如下:
class CommonUtil {public Object obj;public Object getObj() {return obj;}public void setObj(Object obj) {this.obj = obj;}
}
在使用的时候,代码如下:
public static void main(String[] args) {CommonUtil tool = new CommonUtil<>();tool.setObj(2);Integer val1 = (Integer)tool.getObj();tool.setObj("hello java");String val2 = (String)tool.getObj();}
从上述代码可以看出,在获取值时每次都需要强转,稍不留神就容易发生强转错误。所以能不能通过一种方式避免类型强转呢?答案是:泛型。将泛型定义在类上,就可以避免类型转换。 改进代码如下:
class CommonUtil<T> {public T obj;public T getObj() {return obj;}public void setObj(T obj) {this.obj = obj;}
}
在创建实例时把具体类型传入,代码如下:
public static void main(String[] args) {CommonUtil<Integer> tool = new CommonUtil<>();tool.setObj(2);Integer val1 = tool.getObj();CommonUtil<String> tool = new CommonUtil<>();tool.setObj("hello java");String val2 = tool.getObj();}
2、泛型定义方法上
泛型定义在类上有个不太有好的一点,看下面例子,代码如下:
class CommonUtil<T> {public void show(T obj){System.out.println("obj = " + obj);}
}
代码使用代码如下:
CommonUtil<Integer> tool1 = new CommonUtil<>();tool1.show(value);CommonUtil<String> tool2 = new CommonUtil<>();tool2.show("111");CommonUtil<Person> tool2 = new CommonUtil<>();tool2.show(new Person());
发现没,每次调用 show() 方法,都需要在通过创建实例,因为在创建时可以指定具体使用的参数类型。但是这样创建对象太麻烦,怎么解决,可以将泛型定义在方法上,代码如下:
class CommonUtil {public <W> void show(W obj){System.out.println("obj = " + obj);}
}
使用代码如下:
CommonUtil tool1 = new CommonUtil<>();tool1.show(value);tool1.show("111");tool1.show(new Person());
最后在方法调用时传入具体参数类型,这样就可以避免重复创建对象,做到一个方法重复调用,和 Object 非常类似。包括 static 修饰的静态方法也是一样可以使用。代码如下:
class CommonUtil {public static <W> void show(W obj){System.out.println("obj = " + obj);}
}
使用代码如下:
CommonUtil.show(value);CommonUtil.show("111");CommonUtil.show(new Person());
但是泛型定义在静态方法上还要注意,这个静态方法不能使用类上面的泛型。为什么?因为类是在创建时才会指定具体参数类型,而静态方法是在类实例化之前就已经被加载到 JVM,根本不知道你类在创建实例时传入的是什么具体参数类型。错误示例如下:
class CommonUtil<W> {public static <W> void show(W obj){System.out.println("obj = " + obj);}
}
3、泛型定义在接口上
有时候泛型会定义在接口上,代码如下:
public interface Inter<T> {public void print(T obj);
}
接口上的泛型那么可以在子类中指定、或不指定,子类指定具体类型如下:
public InterImpl implements Inter<String> {// 接口上的方法public void print(String obj){}// 子类独有方法protect void show(Object obj){}
}
在使用时,代码如下:
Inter<String> inter = new InterImpl();inter.print("hello");InterImpl impl = new InterImpl();impl.show(new Object());
或者子类中定义泛型,接口定义具体类型,代码如下:
public InterImpl<W> implements Inter<String> {// 接口上的方法public void print(String obj){}// 子类独有方法protect void show(W obj){}
}
在使用时,代码如下:
Inter<String> inter = new InterImpl();inter.print("hello");InterImpl<Integer> impl = new InterImpl();impl.show(new Integer(10));
子类中也不知道具体类型,那么也可以定义泛型,把子类泛型传给接口,代码如下:
public InterImpl<W> implements Inter<W> {// 接口上的方法public void print(W obj){}// 子类独有方法protect void show(W obj){}
}
在使用时,代码如下:
Inter<String> inter = new InterImpl();inter.print("hello");InterImpl<Integer> impl = new InterImpl();impl.show(new Integer(10));
4、泛型通配符
举个例子,代码如下:
public class FanxinDemo {public static void print(Collection<String> list) {list.forEach(e->{System.out.println("e = " + e);});}public static void main(String[] args) {List<String> list1 = new ArrayList<>();list1.add("a");list1.add("b");list1.add("c");List<Integer> list2 = new ArrayList<>();list2.add(1);list2.add(2);print(list1);}
}
可以发现 print() 方法只能输出参数类型是 String 的,其他的参数都不能,怎么可以做到公用这段代码?这里介绍回个泛型通配符 ?
,当你不知道泛型是什么类型是,就可以用这个暂时表示,代码如下:
public class FanxinDemo {public static void print(Collection<?> list) {list.forEach(e->{System.out.println("e = " + e);});}public static void main(String[] args) {List<String> list1 = new ArrayList<>();list1.add("a");list1.add("b");list1.add("c");List<Integer> list2 = new ArrayList<>();list2.add(1);list2.add(2);print(list1);print(list2);}
}
但是假设现在不想让 print() 方法被 Integer 类型参数使用,那么需要怎么做呢?这就需要泛型限定了。
5、泛型限定
泛型限定可以限制参数类型范围,?
这个级别范围太大,不安全,通过 extends、super 关键字来限定范围,但是这两个关键字只能是单继承,所以也是有局限的。限定分为两种:让所有父类可以使用,让所有的子类都可以使用
5.1、让所有父类可以使用
代码如下:
public static void print(Collection<? super Integer> list) {list.forEach(e->{System.out.println("e = " + e);});}
表示让 Integer 所有父类都可以使用 print() 方法。
5.2、让所有子类可以使用
代码如下:
public static void print(Collection<? extends String>> list) {list.forEach(e->{System.out.println("e = " + e);});}
表示让所有的 String 子类可以使用 print() 方法。
相关文章:
Java 基础(1)—泛型简单使用
一、泛型定义及作用 泛型是一种编程机制,允许在编写代码时使用参数化类型,以在编译时实现类型安全。 以下是泛型作用: 增强代码可读性和可维护性:通过在代码中使用泛型参数,可以使代码更清晰、更具有可读性和可维护性…...
内存卡损坏了怎么恢复?
内存卡损坏了怎么恢复?现在我们身边有不少电子设备都是用存储卡来存储数据的。一旦需要方便我们直接导出使用。但这存储的数据也不是一定安全的,当我们将内存卡连接到电脑时,难免会碰到病毒、格式化等提示,在这些情况下,可能会导…...

Mysql使用规范(纯技术和实战建议)
1、事务隔级别: (强制):Repeatable-Read(重复读),且不能在会话操作时临时开启隔离级别。 注: Repeatable-Read(重复读)隔离级别解决不了幻读。 可用 show variables l…...

Netty源码解读-EventLoop(二)
一、简介 NioEventLoop的重要组成:Selector、线程、任务队列,他既会处理io事件,也会处理普通任务和定时任务. 1.下面是Selector,注意有两个哦后面会讲 2.下面的爷爷类提供的Thread变量,其实下面发excutor用的就是这个…...

OSI模型详解
今天,我们详解OSI(Open System Inter-connection Reference Model)模型,来看看工业物联网的网络互联和数据互通。 OSI模型 1984年,国际标准化组织(International Organization for Standardization&#…...

Share Creators完成500万美元融资,以工具化手段帮助企业从数字资产管理中解放
近日,总部位于旧金山湾区的初创公司Share Creators宣布完成了新一轮500万美元的融资,投资方为五源资本和福昕PDF。本轮融资主要用于扩大客户基础,并加速在美国、欧洲和亚洲的业务发展。近几年,企业内容及数字资产管理全球市场正在…...

几个Base64编码工具,也有蹊跷
起因 需求:对一段内容进行base64加密,然后通过url的get请求进行发送到后台,由于加密的内容比较少,base64串也不是很长,我认为此方案可行。 于是找了三个base64编码的在线工具,分别是: 平台1&…...
Python|每日一练|排序|递归|字符串|数组|动态规划|单选记录:以特殊格式处理连续增加的数字|正则表达式匹配|地下城游戏
1、以特殊格式处理连续增加的数字(排序) 贡献者:EricLao 给出一串数字, 程序要把数字按照这样的格式输出,把连续增加的数字用 [x-y] 的形式表示,只显示这一组顺序数字的首位两个数字,不连续增…...

Spring Cloud微服务网关Gateway组件
目录 网关简介 什么是Spring Cloud Gateway Spring Cloud Gateway 功能特征 核心概念 工作原理 Spring Cloud Gateway快速开始 环境搭建 集成Nacos 路由断言工厂(Route Predicate Factories)配置 自定义路由断言工厂 过滤器工厂( …...
cluster nodes(集群节点)
CLUSTER NODES 复制 自3.0.0起可用。 时间复杂度: O(N)其中N是 Cluster 节点的总数 Redis 集群中的每个节点都有其当前集群配置的视图,由已知节点的集合给出,我们与这些节点的连接状态,它们的标志&…...

【Android学习】下载jar慢和gradle慢的情况
目录 问题出现的原因 解决方法 解决Gradle下载问题:手动安装 解决jar包下载慢问题:更改下载源 问题出现的原因 国内访问谷歌被墙导致访问速度慢或者干脆无法下载 解决方法 解决Gradle下载问题:手动安装 访问官网Gradle | Release Candi…...

下一个排列-力扣31-java
一、题目描述整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&…...
前端面试题
1.HTTP request报文结构是怎样的 1.首行是Request-Line包括:请求方法,请求URI,协议版本,CRLF(换行符) 2.首行之后是若干行请求头,包括general-header,request-header或者entity-hea…...

jsp游戏门户网站系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 jsp 游戏门户网站系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql,使…...

Git与IDEA强强联合(HTTPS协议连接)
最近在写项目的时候,在台式机和笔记本之间频繁切换,竟然还是用qq传压缩包,我自己都感觉无语,有git这样强大的版本管理工具,我竟然没想起来。然后也没有相关的博文就想来更新一篇。 那么如何使idea和git强强联合呢&…...
leetcode 第二题:两数相加-C语言实现
题目地址 备注: 不要忘记最后一个进位的可能。可以使用typedef,来简化struct的书写 代码实现: #include<stdio.h> #include<stdlib.h>struct listNode {int val;struct listNode* next; };// 使用typedef typedef struct lis…...
【人工智能】PTP网络时钟服务器在智能驾驶里的重要性
【人工智能】PTP网络时钟服务器在智能驾驶里的重要性 【人工智能】PTP网络时钟服务器在智能驾驶里的重要性 一辆宣称具备L4/L5自动驾驶功能的车辆,如果多个激光雷达之间的时间同步不够精确?如果传感器感知数据通过以太网传输到智驾域控制器的延迟不可控…...
【蓝桥杯集训3】二分专题(3 / 5)
目录 二分模板 1460. 我在哪? - 二分答案 哈希表 1221. 四平方和 - 哈希表 / 二分 1、哈希表 2、二分 自定义排序 1227. 分巧克力 - 113. 特殊排序 - 二分模板 l r >> 1 —— 先 r mid 后 l mid1 —— 寻找左边界 —— 找大于某个数的最小值lr…...

在成都的哪个培训机构学习Java好呢?
自从小课06年进入成都这个IT培训市场以来,短短十几年,招过很多学员,也见证过很多机构的起起落落。心中有万分的感慨,总结下来有这几点分享给大家,在选择培训机构时能看清本质,找到适合自己靠谱的机构学Java…...

传输层重要协议之UDP协议和TCP协议详解
更多关于UDP协议和TCP协议请移步官网:https://www.rfc-editor.org/standards#ISUDP标准协议文档-RFC 768TCP标准协议文档-RFC 793UDP协议详解UDP协议的特点:无连接、不可靠传输、面向数据报和全双工。UDP协议报文结构:关于端口号:…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...