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

泛型的二三事

泛型(Generics)是Java语言的一个重要特性,它允许在定义类、接口和方法时使用类型参数(Type Parameters),从而实现类型安全的代码重用。泛型在Java 5中被引入,极大地增强了代码的灵活性和安全性。以下是关于泛型的详细介绍,包括其基本概念、使用场景和一些高级特性。


1. 泛型的基本概念

1.1 什么是泛型

泛型允许在定义类、接口或方法时使用类型参数,而不是具体的类型。这样可以在运行时动态指定类型,同时保持类型安全。例如:

class Box<T> { // T 是类型参数private T t; // 使用类型参数 Tpublic void set(T t) {this.t = t;}public T get() {return t;}
}

在这个例子中,Box 类使用了类型参数 T,可以在实例化时指定具体的类型,例如:

Box<Integer> intBox = new Box<>();
intBox.set(10);
System.out.println(intBox.get()); // 输出 10
1.2 泛型的好处
  1. 类型安全:编译器会在编译时检查类型是否正确,避免了类型转换错误。

  2. 代码复用:通过泛型可以编写通用的类和方法,减少重复代码。

  3. 减少类型转换:在使用泛型时,不需要显式进行类型转换,代码更加简洁。


2. 泛型的使用场景

2.1 泛型类

泛型类是在类定义时使用类型参数。例如:

class Pair<T, U> {private T first;private U second;public Pair(T first, U second) {this.first = first;this.second = second;}public T getFirst() {return first;}public U getSecond() {return second;}
}

使用时:

Pair<String, Integer> pair = new Pair<>("Hello", 123);
System.out.println(pair.getFirst()); // 输出 Hello
System.out.println(pair.getSecond()); // 输出 123
2.2 泛型接口

泛型接口与泛型类类似,可以在接口定义时使用类型参数。例如:

interface Generator<T> {T next();
}

实现时:

class RandomNumberGenerator implements Generator<Integer> {@Overridepublic Integer next() {return (int) (Math.random() * 100);}
}
2.3 泛型方法

泛型方法是在方法定义时使用类型参数。例如:

public static <T> void printArray(T[] array) {for (T element : array) {System.out.println(element);}
}

调用时:

Integer[] intArray = {1, 2, 3};
String[] strArray = {"Hello", "World"};
printArray(intArray); // 输出 1 2 3
printArray(strArray); // 输出 Hello World

3. 泛型的高级特性

3.1 类型参数的限制(上界)

可以为类型参数指定上界,即类型参数必须是某个类或接口的子类型。例如:

public static <T extends Number> double sum(T[] array) {double total = 0;for (T element : array) {total += element.doubleValue();}return total;
}

调用时:

Integer[] intArray = {1, 2, 3};
System.out.println(sum(intArray)); // 输出 6.0
3.2 泛型通配符(Wildcards)

泛型通配符用于表示未知类型。主要有以下几种:

  1. 无界通配符(?:表示任意类型

    public static void printList(List<?> list) {for (Object element : list) {System.out.println(element);}
    }
  2. 有界通配符(? extends T:表示类型参数是 T 的子类型

    public static void printNumbers(List<? extends Number> list) {for (Number element : list) {System.out.println(element);}
    }
  3. 有界通配符(? super T:表示类型参数是 T 的父类型

    public static void addNumbers(List<? super Integer> list) {list.add(1);list.add(2);
    }
3.3 泛型的类型擦除

Java的泛型在运行时会被擦除,即运行时不会保留泛型类型信息。例如:

Box<Integer> intBox = new Box<>();
Box<String> strBox = new Box<>();
System.out.println(intBox.getClass() == strBox.getClass()); // 输出 true

这意味着运行时 intBoxstrBox 的类型是相同的,都是 Box 类。


4. 泛型的常见问题

4.1 泛型方法的类型推断

Java编译器可以自动推断泛型方法的类型参数。例如:

public static <T> T getFirst(T[] array) {return array[0];
}

调用时:

Integer first = getFirst(new Integer[]{1, 2, 3}); // 编译器推断 T 为 Integer
4.2 泛型与静态方法

泛型方法不能直接定义在静态方法中,因为静态方法属于类本身,而不是类的实例,而泛型类型参数是与实例相关的。例如:

class Box<T> {public static <T> T getFirst(T[] array) { // 错误:静态方法不能使用类的泛型参数return array[0];}
}
4.3 泛型与数组

不能创建泛型数组,因为数组类型在运行时是固定的,而泛型类型在运行时会被擦除。例如:

T[] array = new T[10]; // 错误:不能创建泛型数组

但可以通过其他方式解决,例如:

T[] array = (T[]) new Object[10];

 5.一个泛型代码分析

先来看一个实例:

这段代码是一个Java程序,用于通过泛型方法找到数组中的最大值。以下是对代码的详细分析和一些需要注意的地方:

5.1代码功能

  1. findmaxvalue 方法

    • 这是一个泛型方法,使用了泛型类型 T,并且要求 T 必须实现 Comparable<T> 接口。这意味着传入的数组元素类型必须是可以比较的(例如 IntegerDoubleString 等)。

    • 方法逻辑:

      • 首先检查数组是否为空或为 null,如果是,则抛出 IllegalArgumentException 异常。

      • 将数组的第一个元素初始化为最大值 max

      • 遍历数组,从第二个元素开始,使用 compareTo 方法比较当前元素和 max 的大小。如果当前元素更大,则更新 max

      • 最后返回最大值。

  2. main 方法

    • 定义了一个 Integer 类型的数组 integers1,并将其设置为 null

    • 调用 Alg.findmaxvalue(integers1) 方法,尝试找到数组中的最大值。

    • 将返回的最大值打印到控制台。

5.2代码运行结果

由于 integers1 被设置为 null,在调用 findmaxvalue 方法时,会触发 findmaxvalue 方法中的异常检查逻辑,抛出 IllegalArgumentException 异常,程序会终止并打印异常信息。

5.3输出结果

运行改进后的代码,输出结果为:

5

如果将 integers1 设置为 null 或空数组,程序会输出:

Error: Array is empty or null

 


6. 总结

泛型是Java语言中一个非常强大的特性,它提供了类型安全、代码复用和减少类型转换的好处。通过泛型类、泛型接口和泛型方法,可以编写更加通用和灵活的代码。同时,理解泛型的高级特性(如类型擦除、通配符等)可以帮助你更好地使用泛型,避免常见问题。

如果你有更多关于泛型的具体问题,欢迎随时提问!

相关文章:

泛型的二三事

泛型&#xff08;Generics&#xff09;是Java语言的一个重要特性&#xff0c;它允许在定义类、接口和方法时使用类型参数&#xff08;Type Parameters&#xff09;&#xff0c;从而实现类型安全的代码重用。泛型在Java 5中被引入&#xff0c;极大地增强了代码的灵活性和安全性。…...

编程思想——FP、OOP、FRP、AOP、IOC、DI、MVC、DTO、DAO

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

实现一个动态验证码生成器:Canvas与JavaScript的完美结合

验证码&#xff08;CAPTCHA&#xff09;是现代网站中常见的安全机制&#xff0c;用于区分人类用户和自动化程序。本文将详细介绍如何使用HTML5 Canvas和JavaScript创建一个美观且功能完整的验证码生成器。 一、核心功能概述 这个验证码生成器具有以下特点&#xff1a; 随机生…...

python中 “with” 关键字的取舍问题

自动管理资源&#xff08;自动关闭文件&#xff09; 当你使用 with 打开文件时&#xff0c;文件会在 with 代码块结束后自动关闭&#xff0c;无论是否发生异常。这意味着你不需要显式地调用 f.close() 来关闭文件 示例&#xff1a; with open("words.txt", "r…...

【区块链安全 | 第三十九篇】合约审计之delegatecall(一)

文章目录 外部调用函数calldelegatecallcall 与 delegatecall 的区别示例部署后初始状态调用B.testCall()函数调用B.testDelegatecall()函数区别总结漏洞代码代码审计攻击代码攻击原理解析攻击流程修复建议审计思路外部调用函数 在 Solidity 中,常见的两种底层外部函数调用方…...

Nginx部署spa单页面的小bug

没部署过&#xff0c;都是给后端干的&#xff0c;自己尝试部署了一个下午终于成功了 我遇到的最大的bug是进入后只有首页正常显示 其他页面全是404&#xff0c;于是问问问才知道&#xff0c;需要这个 location / { try_files $uri $uri/ /index.html; } 让…...

linux多线(进)程编程——(6)共享内存

前言 话说进程君的儿子经过父亲点播后就开始闭关&#xff0c;它想要开发出一种全新的传音神通。他想&#xff0c;如果两个人的大脑生长到了一起&#xff0c;那不是就可以直接知道对方在想什么了吗&#xff0c;这样不是可以避免通过语言传递照成的浪费吗&#xff1f; 下面就是它…...

【愚公系列】《Python网络爬虫从入门到精通》050-搭建 Scrapy 爬虫框架

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...

信息安全管理与评估2021年国赛正式卷答案截图以及十套国赛卷

2021年全国职业院校技能大赛高职组 “信息安全管理与评估”赛项 任务书1 赛项时间 共计X小时。 赛项信息 赛项内容 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备配置防护 任务1 网络平台搭建 任务2 网络安全设备配置与防护 第二…...

讲解贪心算法

贪心算法是一种常用的算法思想&#xff0c;其在解决问题时每一步都做出在当前状态下看起来最优的选择&#xff0c;从而希望最终能够获得全局最优解。C作为一种流行的编程语言&#xff0c;可以很好地应用于贪心算法的实现。下面我们来讲一篇关于C贪心算法的文章。 目录 贪心算法…...

高并发秒杀系统设计:关键技术解析与典型陷阱规避

电商、在线票务等众多互联网业务场景中&#xff0c;高并发秒杀活动屡见不鲜。这类活动往往在短时间内会涌入海量的用户请求&#xff0c;对系统架构的性能、稳定性和可用性提出了极高的挑战。曾经&#xff0c;高并发秒杀架构设计让许多开发者望而生畏&#xff0c;然而&#xff0…...

微信小程序实战案例 - 餐馆点餐系统 阶段 2 – 购物车

阶段 2 – 购物车&#xff08;超详细版&#xff09; 目标 把“加入购物车”做成 全局状态&#xff0c;任何页面都能读写在本地 持久化&#xff08;关闭小程序后购物车仍在&#xff09;新建 购物车页&#xff1a;数量增减、总价实时计算、去结算入口打 Git Tag v2.0‑cart 1. …...

Qt 元对象系统探秘:从 Q_OBJECT 到反射编程的魔法之旅

背景说明&#xff1a;Qt 背后的「魔法引擎」 如果你曾用 Qt 写过信号槽&#xff0c;或是在设计器里拖过控件改属性&#xff0c;一定对这个框架的“动态性”印象深刻&#xff1a; 无需手动调用&#xff0c;信号能自动连接到槽函数&#xff1b;无需编译重启&#xff0c;界面上修…...

sql 向Java的映射

优化建议&#xff0c;可以在SQL中控制它的类型 在 MyBatis 中&#xff0c;如果返回值类型设置为 java.util.Map&#xff0c;默认情况下可以返回 多行多列的数据...

Visual Studio未能加载相应的Package包弹窗报错

环境介绍&#xff1a; visulal studio 2019 问题描述&#xff1a; 起因&#xff1a;安装vs扩展插件后&#xff0c;重新打开Visual Studio&#xff0c;报了一些列如下的弹窗错误&#xff0c;即使选择不继续显示该错误&#xff0c;再次打开后任然报错&#xff1b; 解决思路&am…...

【HD-RK3576-PI】Docker搭建与使用

硬件&#xff1a;HD-RK3576-PI 软件&#xff1a;Linux6.1Ubuntu22.04 1.Docker 简介 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言开发&#xff0c;遵循 Apache 2.0 协议。它可以让开发者将应用程序及其依赖项打包到一个轻量级、可移植的容器中&#xff0c;并在任…...

C语言实现用户管理系统

以下是一个简单的C语言用户管理系统示例&#xff0c;它实现了用户信息的添加、删除、修改和查询功能。代码中包含了详细的注释和解释&#xff0c;帮助你理解每个部分的作用。 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX_USERS…...

【websocket】使用案例( ​JSR 356 标准)

目录 一、JSR 356方式&#xff1a;简单示例 1、引入依赖 2、注册端点扫描器 3、编写通过注解处理生命周期和消息 4、细节解读 5、总结 二、聊天室案例 方案流程 1、引入依赖 2、注册端点扫描器 3、编写一个配置类&#xff0c;读取httpsession 4、编写通过注解处理生…...

tcpdump`是一个非常强大的命令行工具,用于在网络上捕获并分析数据包

通过 tcpdump&#xff0c;你可以抓取网络流量&#xff0c;诊断网络问题&#xff0c;或分析通信协议的细节。下面是如何在 Linux 上使用 tcpdump 进行抓包的详细步骤。 1. 安装 tcpdump 在大多数 Linux 发行版中&#xff0c;tcpdump 是默认安装的。如果没有安装&#xff0c;可…...

IS-IS中特殊字段——OL过载

文章目录 OL 过载位 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Datacom专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年04月13日20点12分 OL 过载位 路由过载 使用 IS-IS 的过载标记来标识过载状态 对设备设置过载标记后&#xff…...

【时频谱分析】快速谱峭度

算法配置页面&#xff0c;也可以一键导出结果数据 报表自定义绘制 获取和下载【PHM学习软件PHM源码】的方式 获取方式&#xff1a;Docshttps://jcn362s9p4t8.feishu.cn/wiki/A0NXwPxY3ie1cGkOy08cru6vnvc...

Spring Boot 支持的内嵌服务器(Tomcat、Jetty、Undertow、Netty(用于 WebFlux 响应式应用))详解

Spring Boot 支持的内嵌服务器详解 1. 支持的内嵌服务器 Spring Boot 默认支持以下内嵌服务器&#xff1a; Tomcat&#xff08;默认&#xff09;JettyUndertowNetty&#xff08;用于 WebFlux 响应式应用&#xff09; 2. 各服务器使用示例 (1) Tomcat&#xff08;默认&#xf…...

微软Exchange管理中心全球范围宕机

微软已确认Exchange管理中心&#xff08;Exchange Admin Center&#xff0c;EAC&#xff09;发生全球性服务中断&#xff0c;导致管理员无法访问关键管理工具。该故障被标记为关键服务事件&#xff08;编号EX1051697&#xff09;&#xff0c;对依赖Exchange Online的企业造成广…...

基于AI的Web应用防火墙(AppWall)实战:漏洞拦截与威胁情报集成

摘要&#xff1a;针对Web应用面临的OWASP、CVE等漏洞攻击&#xff0c;本文结合群联AI云防护系统的AppWall模块&#xff0c;详解AI规则双引擎的防御原理&#xff0c;并提供漏洞拦截配置与威胁情报集成代码示例。 一、Web应用安全挑战与AppWall优势 传统WAF依赖规则库更新滞后&a…...

基于Qt的串口通信工具

程序介绍 该程序是一个基于Qt的串口通信工具&#xff0c;专用于ESP8266 WiFi模块的AT指令配置与调试。主要功能包括&#xff1a; 1. 核心功能 串口通信&#xff1a;支持串口开关、参数配置&#xff08;波特率、数据位、停止位、校验位&#xff09;及数据收发。 AT指令操作&a…...

CSS 字体学习笔记

在网页设计中&#xff0c;字体的使用对于提升用户体验和页面美观性至关重要。CSS 提供了一系列字体属性&#xff0c;用于控制文本的显示效果。以下是对 CSS 字体属性的详细学习笔记。 一、字体系列&#xff08;font-family&#xff09; 1. 字体系列的分类 在 CSS 中&#xf…...

《MySQL是怎样运行的》总结笔记

内容太多&#xff0c;主要总结一些自己认为重要的&#xff0c;另外太基础常见可能不会总结上。 字符集和比较规则 MySQL会通过把字符串编码后再进行比较大小并排序&#xff0c;有一些很早的字符集可能会不支持中文&#xff0c;比如ASCII、ISO 8859-1&#xff0c;现在最常用的…...

力扣每日打卡 1922. 统计好数字的数目 (中等)

力扣 1922. 统计好数字的数目 中等 前言一、题目内容二、解题方法1. 暴力解法&#xff08;会超时&#xff0c;此法不通&#xff09;2. 快速幂运算3. 组合计数的思维逻辑分析组合计数的推导例子分析思维小结论 4.官方题解4.1 方法一&#xff1a;快速幂 三、快速幂运算快速幂运算…...

上层 Makefile 控制下层 Makefile 的方法

在复杂的项目中&#xff0c;通常会将项目划分为多个模块或子项目&#xff0c;每个模块都有自己的 Makefile。上层 Makefile 的作用是协调和控制这些下层 Makefile 的构建过程。下面是几种常见的示例&#xff0c;实现上层 Makefile 对下层 Makefile 的控制。 直接调用&#xff1…...

html简易实现推箱子小游戏原理(易上手)

实现效果 使用方向键移动&#xff0c;将橙色箱子推到绿色目标区域&#xff08;黑色块为墙&#xff0c;白色块为可通过区域&#xff0c;蓝球为小人&#xff09; 实现过程 <!DOCTYPE html> <html> <head><title>推箱子小游戏</title><style&g…...