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

Java 基础(1)—泛型简单使用

一、泛型定义及作用

泛型是一种编程机制,允许在编写代码时使用参数化类型以在编译时实现类型安全。 以下是泛型作用:

  1. 增强代码可读性和可维护性:通过在代码中使用泛型参数,可以使代码更清晰、更具有可读性和可维护性。

  2. 提高代码安全性:泛型可以在编译时检查类型,从而防止在运行时出现类型转换错误。

  3. 增加代码重用性:泛型允许在不同的数据类型上编写通用代码,从而提高代码的重用性。

  4. 简化代码:使用泛型可以避免重复编写类似的代码,从而简化代码。

总之,泛型是一种强大的编程机制,它可以帮助开发者编写更具可读性、可维护性、安全性和重用性的代码。

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)—泛型简单使用

一、泛型定义及作用 泛型是一种编程机制&#xff0c;允许在编写代码时使用参数化类型&#xff0c;以在编译时实现类型安全。 以下是泛型作用&#xff1a; 增强代码可读性和可维护性&#xff1a;通过在代码中使用泛型参数&#xff0c;可以使代码更清晰、更具有可读性和可维护性…...

内存卡损坏了怎么恢复?

内存卡损坏了怎么恢复?现在我们身边有不少电子设备都是用存储卡来存储数据的。一旦需要方便我们直接导出使用。但这存储的数据也不是一定安全的&#xff0c;当我们将内存卡连接到电脑时&#xff0c;难免会碰到病毒、格式化等提示&#xff0c;在这些情况下&#xff0c;可能会导…...

Mysql使用规范(纯技术和实战建议)

1、事务隔级别: &#xff08;强制&#xff09;&#xff1a;Repeatable-Read&#xff08;重复读&#xff09;&#xff0c;且不能在会话操作时临时开启隔离级别。 注&#xff1a; Repeatable-Read&#xff08;重复读&#xff09;隔离级别解决不了幻读。 可用 show variables l…...

Netty源码解读-EventLoop(二)

一、简介 NioEventLoop的重要组成&#xff1a;Selector、线程、任务队列&#xff0c;他既会处理io事件&#xff0c;也会处理普通任务和定时任务. 1.下面是Selector&#xff0c;注意有两个哦后面会讲 2.下面的爷爷类提供的Thread变量&#xff0c;其实下面发excutor用的就是这个…...

OSI模型详解

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

Share Creators完成500万美元融资,以工具化手段帮助企业从数字资产管理中解放

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

几个Base64编码工具,也有蹊跷

起因 需求&#xff1a;对一段内容进行base64加密&#xff0c;然后通过url的get请求进行发送到后台&#xff0c;由于加密的内容比较少&#xff0c;base64串也不是很长&#xff0c;我认为此方案可行。 于是找了三个base64编码的在线工具&#xff0c;分别是&#xff1a; 平台1&…...

Python|每日一练|排序|递归|字符串|数组|动态规划|单选记录:以特殊格式处理连续增加的数字|正则表达式匹配|地下城游戏

1、以特殊格式处理连续增加的数字&#xff08;排序&#xff09; 贡献者&#xff1a;EricLao 给出一串数字&#xff0c; 程序要把数字按照这样的格式输出&#xff0c;把连续增加的数字用 [x-y] 的形式表示&#xff0c;只显示这一组顺序数字的首位两个数字&#xff0c;不连续增…...

Spring Cloud微服务网关Gateway组件

目录 网关简介 什么是Spring Cloud Gateway Spring Cloud Gateway 功能特征 核心概念 工作原理 Spring Cloud Gateway快速开始 环境搭建 集成Nacos 路由断言工厂&#xff08;Route Predicate Factories&#xff09;配置 自定义路由断言工厂 过滤器工厂&#xff08; …...

cluster nodes(集群节点)

CLUSTER NODES 复制 自3.0.0起可用。 时间复杂度&#xff1a; O&#xff08;N&#xff09;其中N是 Cluster 节点的总数 Redis 集群中的每个节点都有其当前集群配置的视图&#xff0c;由已知节点的集合给出&#xff0c;我们与这些节点的连接状态&#xff0c;它们的标志&…...

【Android学习】下载jar慢和gradle慢的情况

目录 问题出现的原因 解决方法 解决Gradle下载问题&#xff1a;手动安装 解决jar包下载慢问题&#xff1a;更改下载源 问题出现的原因 国内访问谷歌被墙导致访问速度慢或者干脆无法下载 解决方法 解决Gradle下载问题&#xff1a;手动安装 访问官网Gradle | Release Candi…...

下一个排列-力扣31-java

一、题目描述整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&…...

前端面试题

1.HTTP request报文结构是怎样的 1.首行是Request-Line包括&#xff1a;请求方法&#xff0c;请求URI&#xff0c;协议版本&#xff0c;CRLF&#xff08;换行符&#xff09; 2.首行之后是若干行请求头&#xff0c;包括general-header&#xff0c;request-header或者entity-hea…...

jsp游戏门户网站系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

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

Git与IDEA强强联合(HTTPS协议连接)

最近在写项目的时候&#xff0c;在台式机和笔记本之间频繁切换&#xff0c;竟然还是用qq传压缩包&#xff0c;我自己都感觉无语&#xff0c;有git这样强大的版本管理工具&#xff0c;我竟然没想起来。然后也没有相关的博文就想来更新一篇。 那么如何使idea和git强强联合呢&…...

leetcode 第二题:两数相加-C语言实现

题目地址 备注&#xff1a; 不要忘记最后一个进位的可能。可以使用typedef&#xff0c;来简化struct的书写 代码实现&#xff1a; #include<stdio.h> #include<stdlib.h>struct listNode {int val;struct listNode* next; };// 使用typedef typedef struct lis…...

【人工智能】PTP网络时钟服务器在智能驾驶里的重要性

【人工智能】PTP网络时钟服务器在智能驾驶里的重要性 【人工智能】PTP网络时钟服务器在智能驾驶里的重要性 一辆宣称具备L4/L5自动驾驶功能的车辆&#xff0c;如果多个激光雷达之间的时间同步不够精确&#xff1f;如果传感器感知数据通过以太网传输到智驾域控制器的延迟不可控…...

【蓝桥杯集训3】二分专题(3 / 5)

目录 二分模板 1460. 我在哪&#xff1f; - 二分答案 哈希表 1221. 四平方和 - 哈希表 / 二分 1、哈希表 2、二分 自定义排序 1227. 分巧克力 - 113. 特殊排序 - 二分模板 l r >> 1 —— 先 r mid 后 l mid1 —— 寻找左边界 —— 找大于某个数的最小值lr…...

在成都的哪个培训机构学习Java好呢?

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

传输层重要协议之UDP协议和TCP协议详解

更多关于UDP协议和TCP协议请移步官网&#xff1a;https://www.rfc-editor.org/standards#ISUDP标准协议文档-RFC 768TCP标准协议文档-RFC 793UDP协议详解UDP协议的特点&#xff1a;无连接、不可靠传输、面向数据报和全双工。UDP协议报文结构&#xff1a;关于端口号&#xff1a;…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

linux arm系统烧录

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

2021-03-15 iview一些问题

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

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&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…...