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协议报文结构:关于端口号:…...

BNB Greenfield 成存储赛道“新贵”,BNB 生态的野心与破局
“从BNB Beacon Chain,到BNB Chain,再到BNB Greenfield ,三位一体的 BNB 生态格局正式形成。 ”在今年的2月1日,币安发布了分布式存储链BNB Greenfield,根据白皮书信息,它的特别之处在于其不仅具备基于SP&a…...

【SQL开发实战技巧】系列(十六):时间类型操作(上):日、月、年、时、分、秒之差及时间间隔计算
系列文章目录 【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧…...

JavaScript知识点总结
JavaScript 一、介绍: 1.JavaScript是一种专门在浏览器编译并执行的编程语言 2.JavaScript处理用户与浏览器之间请求问题 3.JavaScript采用【弱类型编程语言风格】对【面向对象思想】来进行实现的编程语言 二、弱类型编程语言风格 VS 强类型编程语言风格 …...

adb命令记录
一、获取系统版本 adb shell getprop ro.build.version.release 二、手机文件拉取到电脑 adb命令 : adb pull source_path dest_path 示例: adb pull /sdcard/Movies/app_layout.txt ./ 从手机拉取app_layout.txt文件到当前路径。 三、电脑文件推送…...

9.Docker Swarm
Docker Swarm 基本概念 Swarm是使用SwarmKit构建的 Docker 引擎内置(原生)的集群管理和编排工具。Docker Swarm是 Docker 官方三剑客项目之一,提供 Docker 容器集群服务,是 Docker 官方对容器云生态进行支持的核心方案。 使用它…...

基于tensorflow keras DNN神经网络训练预测豆瓣中文影评差评好评 附完整代码 +数据
首先看视频:https://www.bilibili.com/video/BV1r84y1p7q3/?spm_id_from=333.999.0.0 附完整的代码数据 完整的代码项目: 主要代码: # 导入包 import csv import jieba import tensorflow as tf from tensorflow...

商城系统必备营销工具(五)——积分商城
做商城,流量必不可少,日活跃度也很重要。现在各大APP、网站、小程序和微商城,基本都在为了巩固流量做积分商城,虽然已经随处可见,但很多企业商家却并没有将积分商城运作起来,积分商城也没有人浏览兑换商品。…...

SpringBoot08:Shiro
什么是Shiro? 一个Java的安全(权限)框架,可以完成认证、授权、加密、会话管理、Web集成、缓存等 下载地址:Apache Shiro | Simple. Java. Security. 快速启动 先在官网找到入门案例:shiro/samples/quick…...

进击中的 Zebec 生态,Web2 与 Web3 世界的连接器
虽然从意识形态上看,Web2世界与Web3世界存在着不同的逻辑,但我们同样看到,随着加密资产领域的发展,其正在作为优质投资品,被以Paypal、高盛等主流机构重视与接受。当然,除了作为投资者品外,近年…...

SpringCloud保姆级搭建教程五---Redis
首先,这个和微服务没有直接的关系,只是在代码开发当中要使用的一个工具而已,为了提高这个系统的性能,加快查询效率等方面而使用它1、首先,要先安装redis到电脑上,这里依然是在windows上演示,之后…...