Java进阶篇--泛型
前言
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。它允许在定义类、接口和方法时使用类型参数。这种技术使得在编译期间可以使用任何类型,而不是仅限于特定的类型。这大大提高了代码的灵活性和可重用性。
泛型的基本语法是在类、接口或方法名的后面加上尖括号(< >),并在其中定义类型参数。例如:
public class Box<T> { private T t; public void set(T t) { this.t = t; } public T get() { return t; }
}
在上述代码中,T 是一个类型参数,可以代表任何类型。你可以在类的定义中使用 T 来表示泛型,然后在方法中使用 T 来表示任何类型的对象。
Java 泛型的特性:
类型参数
在定义泛型类或方法时,使用类型参数代替具体的类型。类型参数在使用前需要命名,通常使用大写字母来表示。例如,在上述的 Box 类中,我们使用 T 作为类型参数。
java 中泛型标记符:
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
- ? - 表示不确定的 java 类型
类型限定
Java 泛型的类型参数有限制,不能是 void、boolean、char、byte、short、int、float、double等原始类型。此外,Java 泛型的类型参数只能是类类型(包括 Class、接口类型或枚举类型),不能是数组类型或函数类型。
通配符类型参数
除了具体类型作为类型参数外,Java 泛型还支持通配符类型参数。通配符类型参数表示可以接受任何类型的参数,例如 List<?> 表示可以接受任何类型的 List。通配符类型参数还有两种限定符:
- ? extends T:表示该泛型只能接受 T 或 T 的子类。例如,List<? extends Number> 可以接受 List<Number>、List<Integer> 等,但不能接受 List<String>。
- ? super T:表示该泛型可以接受任何父类或等于 T 的类型。例如,List<? super Number> 可以接受 List<Number>、List<Object> 等,但不能接受 List<String>。
泛型方法
除了泛型类外,还可以定义泛型方法。泛型方法允许在方法的返回值和参数类型中使用类型参数。例如:
public <T> T getFirst(List<T> list) { return list.get(0);
}
在上述代码中,我们定义了一个泛型方法 getFirst,它接受一个 List<T> 类型的参数,并返回一个 T 类型的对象。
泛型继承
当一个类继承一个泛型类时,子类可以选择是否继续使用父类的类型参数。例如:
public class MyBox extends Box<Integer> { // ...
}
在上述代码中,我们定义了一个子类 MyBox,它继承了 Box<Integer> 类。这样,在 MyBox 类中,我们可以直接使用 Integer 作为类型参数,而不必重新定义一个新的类型参数。
类型擦除
Java 泛型的类型信息在编译后的代码中会被擦除,只剩下原始类型的信息。这是为了保持 Java 代码的兼容性和跨平台性。因此,在使用泛型时,不能在运行时通过反射来获取泛型的具体类型信息。
以下是一个简单代码示例,演示了类型擦除的概念:
public class MyClass<T> {// 定义一个泛型类MyClass,其中T是一个类型参数private T value; // 定义一个私有成员变量value,它的类型是泛型参数Tpublic MyClass(T value) { // 定义一个构造函数,接受一个类型为T的参数this.value = value; // 将参数值赋值给成员变量value}public T getValue() { // 定义一个公共方法getValue,返回类型为T的值return value; // 返回成员变量value的值}public static void main(String[] args) {// 创建两个不同类型的实例MyClass<Integer> intExample = new MyClass<>(123); // 创建一个Integer类型的MyClass实例,并将其引用赋给intExample变量MyClass<String> stringExample = new MyClass<>("Hello"); // 创建一个String类型的MyClass实例,并将其引用赋给stringExample变量// 调用getValue方法并打印结果System.out.println(intExample.getValue()); // 调用intExample的getValue方法并打印返回值,输出123System.out.println(stringExample.getValue()); // 调用stringExample的getValue方法并打印返回值,输出Hello}
}
有界类型参数
Java 泛型还支持有界类型参数。有界类型参数允许在定义泛型类或方法时,对类型参数进行限制。例如:
public class MyList<T extends Number> { private List<T> list; // ...
}
在上述代码中,我们定义了一个泛型类 MyList,其中的类型参数 T 必须是 Number 或其子类。这样,在使用 MyList 时,只能使用符合这个条件的类型作为类型参数。
使用泛型的注意事项:
- 泛型不能使用基本类型,如int、float等,必须使用其包装类,如Integer、Float等。
- 运行时类型检查。Java的泛型是通过类型擦除实现的,在运行时类型检查被擦除,因此运行时可能抛出异常。
- 对于有界类型参数,子类不能继承父类并改变类型参数的限定范围。例如,如果父类中的类型参数限定为某个类,子类中的类型参数必须是这个类的子类或者相同。
- 不能使用泛型数组,如ArrayList<T>[]。
- 不能使用泛型构造对象,如T t = new T();。
- 在静态方法中使用泛型,泛型变量不可以使用static关键字来修饰。
- 不可以使用泛型类继承Exception类,即泛型类不可以作为异常被抛出。
- 对于equals方法,如果使用泛型类,可能会出现类型转换异常,因此需要重写equals方法。
- 如果某个泛型类还有同名的非泛型类,不要混合使用,坚持使用泛型类。
- 泛型的推断。如果泛型的限定类型已经确定,可以使用泛型的推断,即直接使用变量类型作为限定类型,不需要再写出限定类型。
实例
import java.util.ArrayList;
import java.util.List;// 定义一个泛型类 User,使用通配符类型参数
class User<T> {// 定义一个存储对象引用的列表,其中T代表任意类型List<T> friends;// 构造函数,初始化朋友列表public User() {this.friends = new ArrayList<>();}// 泛型方法,接受一个类型为T的参数并返回一个类型为T的对象public T getLastFriend() {// 返回列表中的最后一个朋友,如果列表为空则返回nullif (friends.isEmpty()) {return null;} else {return friends.get(friends.size() - 1);}}// 重写toString方法,用于打印用户和朋友列表@Overridepublic String toString() {return "User{" +"friends=" + friends +'}';}
}// 定义一个子类 StringUser,继承自泛型类 User,并指定类型参数为 String
class StringUser extends User<String> {// 重写父类的toString方法,只打印字符串类型的朋友列表@Overridepublic String toString() {return "StringUser{" +"friends=" + friends +'}';}
}// 主类,测试以上定义的泛型类和子类
public class MyClass {public static void main(String[] args) {// 创建一个 User<String> 对象,存储字符串类型的朋友User<String> user = new User<>();((User<String>) user).friends.add("Alice");((User<String>) user).friends.add("Bob");System.out.println(user); // 输出:User{friends=[Alice, Bob]}System.out.println(user.getLastFriend()); // 输出:Bob// 创建一个 StringUser 对象,同样存储字符串类型的朋友StringUser stringUser = new StringUser();stringUser.friends.add("Charlie");stringUser.friends.add("Dave");System.out.println(stringUser); // 输出:StringUser{friends=[Charlie, Dave]}System.out.println(stringUser.getLastFriend()); // 输出:Dave}
}
代码解释:
- User<T> 是一个泛型类,其中 T 是类型参数。这意味着可以创建 User<String>, User<Integer>, User<Object> 等不同类型的用户对象。这个类有一个通配符类型参数 T,这意味着可以使用任意类型来创建用户对象。
- getLastFriend() 方法是一个泛型方法,它接受一个类型为 T 的参数并返回一个类型为 T 的对象。这个方法从朋友列表中返回最后一个朋友。如果列表为空,则返回 null。注意,由于类型擦除,Java在运行时并不保留泛型的具体类型信息。因此,不能在运行时知道 T 的具体类型。然而,这并不影响使用泛型。
- StringUser 是 User<String> 的子类。可以使用有界类型参数来继承泛型类并指定具体的类型。在这种情况下,StringUser 只可以存储字符串类型的朋友。由于子类中没有重写 getLastFriend() 方法,它将使用父类的实现。但是,我们在 StringUser 中重写了 toString() 方法,以只打印字符串类型的朋友列表。
- 在 MyClass 类中,我们创建了一个 User<String> 对象和一个 StringUser 对象。我们可以看到,尽管运行时不知道泛型的具体类型(由于类型擦除),但是我们仍然可以创建不同类型的用户对象。此外,由于有界类型参数,StringUser 只可以存储字符串类型的朋友。
相关文章:
Java进阶篇--泛型
前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。它允许在定义类、接口和方法时使用类型参数。这种技术使得在编译期间可以使用任何类型,而…...
android framework之Applicataion启动流程分析
Application启动流程分析 启动方式一:通过Launcher启动app 启动方式二:在某一个app里启动第二个app的Activity. 以上两种方式均可触发app进程的启动。但无论哪种方式,最终通过通过调用AMS的startActivity()来启动application的。 根据上图…...
Linux Day10 ---Mybash
目录 一、Mybash介绍 1.1.mybash.c 打印函数 分割函数 命令函数 二、Mybash实现 2.1.打印函数 2.1.1需要使用到的功能函数 1.获取与当前用户关联的UID 2.获取与当前用户的相关信息---一个结构体(passwd) 3.获取主机信息 4.获取当前所处位置 5.给…...
Flask-Sockets和Flask-Login联合实现websocket的登录认证功能
flask_login 提供了一个方便的方式来管理用户会话。当你在 Flask 的 HTTP 视图中使用它时,你可以简单地使用 login_required 装饰器来确保用户已登录。 但是,flask_sockets 并没有直接与 flask_login 集成。如果你想在建立 WebSocket 连接时检查用户是否…...
东盟全面覆盖?长城战略部署核心区域市场,首个百万粉丝国产品牌
根据最新消息,长城汽车在东南亚地区取得了巨大的成功,成功进军了亚洲最大的汽车市场之一-印度尼西亚。这标志着长城汽车已经实现了东盟核心市场的全面覆盖,成为全球布局的重要一步。 在过去的几年里,长城汽车在东盟地区的市场布局…...
基于PHP的电脑商城系统
有需要请加文章底部Q哦 可远程调试 基于PHP的电脑商城系统 一 介绍 此电脑商城系统基于原生PHP开发,数据库mysql,前端bootstrap。用户可注册登录,购物下单,评论等。管理员登录后台对电脑商品,用户,订单&a…...
无客户端网络准入方案,为集成电路企业终端管理开启省事更省心模式
宁盾无客户端网络准入控制方案正在成为先进制造、高科技互联网企业等创新型客户的优选方案。创新型客户以技术密集型、研发人员占比高著称,在进行网络准入建设时,如何平衡好用户体验与顺利达成项目预期之间的矛盾,是创新企业 IT 安全团队格外…...
5G与4G的RRC协议之异同
什么是无线资源控制(RRC)? 我们知道,在移动通信中,无线资源管理是非常重要的一个环节,首先介绍一下什么是无线资源控制(RRC)。 手机和网络通过无线信道相互通信,彼此交…...
横扫“盲区”、“看透”缺陷,维视智造推出短波红外相机
在可见光领域,工业相机的视觉应用已经十分成熟,但在日常的客户咨询中,我们也经常接到一些“超纲需求”——客户想要检测“白底上的白色缺陷”、“不透明包装内的透明物体有无”等,均属于可见光无法实现的检测,而市面上…...
cgo踩坑:交叉编译过程出现的问题could not determine kind of name for C.XXX
尝试了网上的几种解决方法,都不行,现总结起来: 确认 /* #include <stdio.h> */ import "C"不要有空行 确认你引用的头文件存在(stdio.h这种编译器自带的不需要你确认) 如果引用了多个包,…...
自然语言处理(NLP)技术的例子
以下是几个自然语言处理(NLP)技术的例子: 机器翻译:机器翻译是将一种自然语言的文本转换成另一种语言的文本的过程。这种技术应用于在线翻译器、多语言聊天机器人、多语言搜索引擎等地方。 文本分类:文本分类将文本分…...
Python“牵手”义乌购商品列表数据,关键词搜索义乌购API接口数据,义乌购API接口申请指南
义乌购平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范,义乌购API接口是指通过编程的方式,让开发者能够通过HTTP协议直接访问义乌购平台的数据,包括商品信息、店铺信息、物流信息等,从而实现义…...
ip_vs 原理解析 (四)hook 后的开始 NF_INET_LOCAL_IN
文章目录 ip_vs hook 后NF_INET_LOCAL_IN 本章重点: k8s 如何利用 ip_vs 实现源 IP 会话亲和性。 ip_vs hook 后 NF_INET_LOCAL_IN 根据优先级依次是 ip_vs_reply4,ip_vs_remote_request4 ip_vs_reply4| -- ip_vs_out| -- skb_to_full_sk(skb…...
分布式之CAP理论与BASE理论
CAP理论 CAP:一致性(consistency)、可用性(Availability)、分区容错(partition-tolerance)。CAP定律说的是在一个分布式计算机系统中,一致性,可用性和分区容错性这三种保证无法同时…...
Java之初始化顺序实践
功能概述 在创建Java对象时,需要将对象中的成员变量进行初始化后,才能调用对象的构造方法创建对象。本文中将会讲解初始化时父类与子类对应的顺序。 功能实践 场景1:父类、子类的初始化顺序 用例代码 Test public void test_init_order(…...
静态库与动态链接库,第三方库集成到VS
目录 介绍静态库与动态链接库静态库动态链接库 如何将第三方库集成到VS上VS属性管理器配置静态库配置动态链接库属性管理器其他的内容MKL库的安装boost库的安装 介绍 众所周知,.c文件或者.cpp文件变成.exe文件需要经历四个过程 分别是预处理,编译&#…...
生态经济学领域里的R语言机器学(数据的收集与清洗、综合建模评价、数据的分析与可视化、数据的空间效应、因果推断等)
近年来,人工智能领域已经取得突破性进展,对经济社会各个领域都产生了重大影响,结合了统计学、数据科学和计算机科学的机器学习是人工智能的主流方向之一,目前也在飞快的融入计量经济学研究。表面上机器学习通常使用大数据…...
【ROS】自定义消息方面的bug总结(1)
根据需要创建功能包 一类引用ros库函数的一类是自己定义的消息类型 库函数中有的可以直接在创建功能包的时候添加依赖,也可以在CMakeLists.txt中手动添加 catkin_create_pkg crepes roscpp rospy std_msgs nav_msgs sensor_msgs geometry_msgs创建文件夹msg…...
CTF-XXE(持续更新,欢迎分享更多相关知识点的题目)
知识 实例 BUU [PHP]XXE 进来看到 然后一起看 Write BUU XXE COURSE 1 进来看到 一起看 write NSS [NCTF2019]Fake XML cookbook 反正是XXE 直接整 write [NCTF 2019]True XML cookbook 不整花里胡哨,解题在最下面 write 与博主不同,我通过…...
Python工具箱系列(四十一)
使用zip批量压缩文件 前文的代码示例了使用gzip对单个文件进行压缩。本文示例使用更通用的zipfile来批量压缩文件。zipfile也是python内置的库,使用起来非常方便。废话不说,直接上代码示例。 import dbm import glob import zipfile# 保存压缩计划的库名…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
