面试突击:Java 中的泛型
本文已收录于:https://github.com/danmuking/all-in-one(持续更新)
前言
哈喽,大家好,我是 DanMu。今天想和大家聊聊 Java 中的泛型。
什么是泛型?
Java 泛型(Generics) 是 JDK 5 中引入的一个新特性。它允许我们通过预先定义模板,为多种不同的数据类型执行相同的逻辑,实现更好的代码复用。
Java 编译器实现了对泛型参数进行检测,并且运行我们通过泛型参数来指定传入的对象类型,比如ArrayList<Integer> list = new ArrayList<Integer>()就指定了这个 ArrayList 中只能存放 Integer 对象,如果传入其他类型的对象就会报错。
为什么需要泛型?
引入泛型的意义在于:
- 适用于多种数据类型执行相同的代码(代码复用)
如果没有泛型,即使是通用的逻辑,也需要针对每种类型单独进行一次重载,比如下面这个例子:
private static int add(int a, int b) {System.out.println(a + "+" + b + "=" + (a + b));return a + b;
}private static float add(float a, float b) {System.out.println(a + "+" + b + "=" + (a + b));return a + b;
}private static double add(double a, double b) {System.out.println(a + "+" + b + "=" + (a + b));return a + b;
}
这不是耽误我赚个小目标的进度嘛。为了帮助我们更快的赚到小目标,Java 贴心的为我们设计了泛型方法,现在我们可以用泛型的方式来重写一下上面的代码:
private static <T extends Number> add(T a, T b) {System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));return a.doubleValue() + b.doubleValue();
}
在这端代码中,使用了一个泛型<T extends Number>来代替了上面出现的所有数字类型,在使用时,我们只需要指定 T 的类型,编译器就会自动的帮助我们将方法中的 T 转换为对应的类型,因此只需要一个函数就能实现所有数字类型的加法。
- 泛型中的类型可以在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
比如下面这个例子:
List list = new ArrayList();
list.add("联系时长");
list.add(2.5);
list.add("的练习生");
在上述 list 中,list 中的所有元素都是Object类型,因此,我们在取出集合元素时需要手动进行强制类型转化,将Object 转换到具体的目标类型,不仅麻烦而且很容易出现java.lang.ClassCastException异常。
通过引入泛型,它能够为我们进行类型的约束,提供编译前的检查:
List<String> list = new ArrayList<String>(); // list中只能放String, 不能放其它类型的元素
如何使用泛型?
泛型主要的使用方式有三种:泛型类、泛型接口、泛型方法。
泛型类:
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{private T key;public Generic(T key) {this.key = key;}public T getKey(){return key;}
}
如何实例化泛型类:
Generic<Integer> genericInteger = new Generic<Integer>(123456);
泛型接口:
public interface Generator<T> {public T method();
}
实现泛型接口,不指定类型:
class GeneratorImpl<T> implements Generator<T>{@Overridepublic T method() {return null;}
}
实现泛型接口,指定类型:
class GeneratorImpl<T> implements Generator<String>{@Overridepublic String method() {return "hello";}
}
泛型方法:
public static < E > void printArray( E[] inputArray )
{for ( E element : inputArray ){System.out.printf( "%s ", element );}System.out.println();
}
使用:
// 创建不同类型数组:Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3 };
String[] stringArray = { "Hello", "World" };
printArray(intArray);
printArray(stringArray);
注意:
public static <E> void printArray(E[] inputArray )一般被称为静态泛型方法;在 Java 中泛型只是一个占位符,必须在传递类型后才能使用。类在实例化时才能真正的传递类型参数,由于静态方法的加载先于类的实例化,也就是说类中的泛型还没有传递真正的类型参数,静态的方法的加载就已经完成了,所以静态泛型方法是没有办法使用类上声明的泛型的。只能使用自己声明的
泛型的上下限
有时候我们不希望某个泛型能够被所有类型使用,比如这个例子:
private static void printText(T a) {System.out.println(a.text);
}// 使用
add(1);
在方法中将会输出传入对象的 text 属性,但是如果当传入对象没有 text 属性或者 text 属性不可以直接访问,程序就会报错。OMG!这就很糟糕了,并且这段代码可以很容易的通过编译检查,只有在运行时错误才会被发现。为了减少这种情况的发生,我们需要一种机制,能够将泛型允许接受的对象类型限制在一定的范围内。
在 Java 中提供了 extends 和 super 两个关键字来限制泛型的范围:
extends 关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类
class Info<T extends Number>{ // 此处泛型只能是数字类型private T var ; // 定义泛型变量public void setVar(T var){this.var = var ;}public T getVar(){return this.var ;}public String toString(){ // 直接打印return this.var.toString() ;}
}
public class demo1{public static void main(String args[]){Info<Integer> i1 = new Info<Integer>() ; // 声明Integer的泛型对象Info<List> i1 = new Info<List>() ; // 报错}
}
super 关键字声明了类型的下界,表示参数化的类型可能是指定的类型,或者是此类型的父类
public class demo2 {public static void main(String[] args) {List<? super Number> number = new ArrayList<Number>();number.add(314);String a = "test";// number.add(a); 报错getUperNumber(number);}// <?> 无限制通配符public static void getUperNumber(List<?> data) {System.out.println("data :" + data.get(0));}
}
如果需要进行多种条件的限制,可以用 & 将多个条件连接起来:
public class Client {//工资低于2500元的上斑族并且站立的乘客车票打8折public static <T extends Staff & Passenger> void discount(T t){if(t.getSalary()<2500 && t.isStanding()){System.out.println("恭喜你!您的车票打八折!");}}public static void main(String[] args) {discount(new Me());}
}
点关注,不迷路
好了,以上就是这篇文章的全部内容了,如果你能看到这里,非常感谢你的支持!
如果你觉得这篇文章写的还不错, 求点赞👍 求关注❤️ 求分享👥 对暖男我来说真的 非常有用!!!
白嫖不好,创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !
最后推荐我的IM项目DiTing(https://github.com/danmuking/DiTing-Go),致力于成为一个初学者友好、易于上手的 IM 解决方案,希望能给你的学习、面试带来一点帮助,如果人才你喜欢,给个Star⭐叭!
参考资料
Java 基础 - 泛型机制详解
相关文章:
面试突击:Java 中的泛型
本文已收录于:https://github.com/danmuking/all-in-one(持续更新) 前言 哈喽,大家好,我是 DanMu。今天想和大家聊聊 Java 中的泛型。 什么是泛型? Java 泛型(Generics) 是 JDK 5…...
3_2、MFC常用控件用法:组合框、滚动条和图片控件
MFC控件用法 1、组合框1.1 简介1.2 创建CComboBox类的主要成员函数 1.3 实例 2、滚动条控件2.1 简介2.2 创建CScrollBar类的主要成员函数 2.3 实例 3、图片控件3.1 简介3.2 创建图片控件静态加载图片图片控件动态加载图片 1、组合框 1.1 简介 组合框其实就是把一个编辑框和一…...
如何使用gprof对程序进行性能分析
如何使用gprof对程序进行性能分析 目录 1 gprof概述 2 gprof原理简述 3 gprof使用 3.1 gprof使用简述 3.2 gprof使用示例 4 小结 1 gprof概述 gprof 是 一个 GNU 的程序性能分析工具,可以用于分析C\C程序的执行性能。gprof工具可以统计出各个函数的调用次数、执…...
四川汇聚荣科技有限公司靠谱吗?
在如今这个信息爆炸的时代,了解一家公司是否靠谱对于消费者和合作伙伴来说至关重要。四川汇聚荣科技有限公司作为一家位于中国西部地区的企业,自然也受到了人们的关注。那么,这家公司究竟如何呢?接下来,我们将从多个角度进行深入…...
可灵王炸更新,图生视频、视频续写,最长可达3分钟!Runway 不香了 ...
现在视频大模型有多卷? Runway 刚在6月17号 发布Gen3 ,坐上王座没几天; 可灵就在6月21日中午,重新夺回了王座!发布了图生视频功能,视频续写功能! 一张图概括: 二师兄和团队老师第一…...
oracle中使用临时表GLOBAL TEMPORARY TABLE
需要在存储过程中返回一个临时结果集,这个结果集又是多个语句通过循环查询出来的,这时候就想到了将结果插入到临时表中,然后返回临时表的数据的思路,于是有了以下操作: 1.创建临时表 -- Create table create global …...
Gradio入门—快速开始
目录 安装构建您的第一个演示分享您的演示核心 Gradio 课程聊天机器人gr.ChatInterface自定义演示gr.BlocksGradio Python 和 JavaScript 生态系统 Gradio 是一个开源 Python 软件包,可让您快速为机器学习模型、API 或任何任意 Python 函数构建演示或 Web 应用程序。…...
AOP应用之系统操作日志
本文演示下如何使用AOP,去实现系统操作日志功能。 实现步骤 引入AOP包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.6</version></de…...
海外云手机自动化管理,高效省力解决方案
不论是企业还是个人,对于海外社媒的营销都是需要自动化管理的,因为自动化管理不仅省时省力,而且还节约成本; 海外云手机的自动化管理意味着什么?那就是企业无需再投入大量的人力和时间去逐一操作和监控每一台设备。 通…...
后仿真中的 《specify/endspecify block》之(5)使用specify进行时序仿真
前面我们学习了specify...endspecify 具体是什么东西。今天,我们使用specify block 中定义的延时,来进行一次仿真。看看到底是背后如何运转的呢。 一 基本例子 一个用 specify 指定延迟的与门逻辑描述如下: module and_gate(output Z,input A, B);assign Z = A & …...
win10/11磁盘管理
win10/11磁盘管理 合并磁盘分区的前提是你的两个磁盘区域是相邻的,比如如下: 如果需要吧这个磁盘进行分解,你可以选择压缩一部分磁盘或者是直接删除卷 我这里的话,因为压缩出来的卷和C盘好像是不相邻的(我之前做过&…...
【昇思初学入门】第四天打卡
数据变换Transforms 心得体会 MindSpore提供了丰富的数据变换工具,针对图像数据可以使用如Rescale、Normalize和HWC2CHW等,且使用Compose类允许我们定义一个变换序列,并将它们作为一个整体应用到数据上。 composed transforms.Compose([v…...
禁用/屏蔽 Chrome 默认快捷键
Chrome 有一些内置的快捷键,但是它并没有像其他软件一样提供管理快捷键的界面。在某些时候,当我们因为个人需求希望禁用 Chrome 某些快捷键时,又无从下手。 好在有开发者开发了 Chrome 插件,可以禁用 Chrome 快捷键的插件&#x…...
移动端+PC端应用模式的智慧城管综合执法办案平台源码,案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析
城市管理综合执法管理平台实现执法办案、业务全流程在线办理,依托移动端PC端的“两端”应用模式,保障能够通过信息化手段进行日常的执法办案工作,强化执法监督功能。提供了案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析等功能&a…...
AI音乐大模型时代:版权归属与创意产业的新生长点
AI在创造还是毁掉音乐? 简介:最近一个月,轮番上线的音乐大模型,一举将素人生产音乐的门槛降到了最低,并掀起了音乐圈会不会被AI彻底颠覆的讨论。短暂的兴奋后,AI产品的版权归属于谁,创意产业要…...
C++函数作为参数
C++函数作为参数 在C++中,函数作为另一个函数的参数是非常常见的做法,特别是在处理回调函数和泛型编程时。我们展示了如何在C++中将函数作为参数传递给另一个函数,包括普通函数、std::function 和 std::bind、lambda表达式以及类成员函数。每种方法都有其独特的优势,可以根…...
考前刷题练手感(北航期末往年数据结构编程题)
本次因为是考前一天极速刷题,所以没有讲解,若有问题可私信。 目录 一、 查找同时空人员二、 老鼠回家-无回路三、函数调⽤关系四、东二食堂模拟五、栈帧 一、 查找同时空人员 【问题描述】 假设一共有6个手机基站,都具有记录手机连接基站状…...
Android记录9--实现转盘效果
自定义View /2013.10.16_TurnPlate_Demo/src/com/wwj/turnplate/TurnPlateView.java package com.wwj.turnplate; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; im…...
【Oracle APEX开发小技巧1】转换类型实现显示小数点前的 0 以 及常见类型转换
在 apex 交互式式网格中,有一数值类型为 NUMBER,保留小数点后两位的项,在 展示时小数点前的 0 不显示。 效果如下: 转换前: m.WEIGHT_COEFFICIENT 解决方案: 将 NUMBER(20,2…...
GRIT论文阅读笔记
一篇试图统一生成任务和编码任务的工作,就是把只能完成生成任务的GPT改成既能生成又能encode。思路其实很简单,就是在输入的时候添加instruction tokens来指引模型做representation还是generation,然后各自算损失。representation任务用的是d…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
Android屏幕刷新率与FPS(Frames Per Second) 120hz
Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数,单位是赫兹(Hz)。 60Hz 屏幕:每秒刷新 60 次,每次刷新间隔约 16.67ms 90Hz 屏幕:每秒刷新 90 次,…...
