Java基础 - 泛型(常见用法)
文章目录
- 泛型类
- 泛型方法
- 泛型类派生子类
- 示例 1:子类固定父类泛型类型(`StringBox` 继承自 `Box<String>`)
- 示例 2:子类保留父类泛型类型(`AdvancedBox<T>` 继承自 `Box<T>`)
- 示例 3:添加子类自己的泛型参数(`KeyValuePair<K,V>` 继承自 `Pair<K>`)
- 示例 4:约束父类类型边界(`IntCalculator` 继承自 `NumberCalculator<Integer>`)
- 类型通配符
- 示例 1:无界通配符(`<?>`)
- 示例 2:上界通配符(`<? extends Number>`)
- 示例 3:下界通配符(`<? super Integer>`)
泛型类
泛 型 类 就 是 把 泛 型 定 义 在 类 上 , 用 户 使 用 该 类 的 时 候 , 才 把 类 型 明 确 下 来 。 这样的话, 用户明确了什么类型 , 该类就代表着什么类型 , 用户在使用的时候就不用担心强转的问题, 和运行时转换异常的问题了。
public class Box<T> {private T content; // 泛型字段public void setContent(T content) {this.content = content;}public T getContent() {return content;}public static void main(String[] args) {// 存储字符串类型Box<String> stringBox = new Box<>();stringBox.setContent("Hello Generics");System.out.println(stringBox.getContent()); // 输出: Hello Generics// 存储整数类型Box<Integer> intBox = new Box<>();intBox.setContent(100);int value = intBox.getContent(); // 无需强制类型转换System.out.println(value); // 输出: 100}
}
关键点:
Box<T>的 T 是类型参数,使用时由开发者指定具体类型(如 String 或 Integer)。- 类型安全:例如 stringBox.setContent(100) 会在编译时报错。
泛型方法
除了在类上使用泛型 ,我们可能就 仅 仅 在 某 个 方 法 上 需 要 使 用 泛 型 , 外界仅仅是关心该方法 , 不关心类其他的属性 , 这样的话 , 我们在整个类上定义泛型 , 未免就有些大题小作了 。 那么此时 , 我们可以采用泛型方法。
public class MaxFinder {/*** 泛型方法:找到数组中的最大值(要求元素类型实现 Comparable 接口)* @param array 输入数组* @return 最大值*/public static <T extends Comparable<T>> T findMax(T[] array) {if (array == null || array.length == 0) {throw new IllegalArgumentException("数组不能为空");}T max = array[0];for (T item : array) {if (item.compareTo(max) > 0) {max = item;}}return max;}public static void main(String[] args) {Integer[] integers = {5, 8, 2, 10};Integer maxInt = findMax(integers); // 调用时类型为 IntegerSystem.out.println("Max Integer: " + maxInt); // 输出: 10String[] fruits = {"Apple", "Banana", "Mango"};String maxFruit = findMax(fruits); // 调用时类型为 StringSystem.out.println("Max String: " + maxFruit); // 输出: Mango(按字典序比较)}
}
关键点:
<T>声明在方法返回类型前,表示这是一个泛型方法,独立于类是否泛型。<T extends Comparable<T>>确保类型 T 的对象可以相互比较(通过 compareTo 方法)。- 类型安全:拒绝不可比较的类型:例如 findMax(new Object[]{…}) 会编译失败。
- 返回
T类型,确保返回元素类型与输入数组类型完全一致。
泛型类派生子类
前 面 我 们 已 经 定 义 了 泛型 类 , 泛 型 类 是 拥有泛型特性的类 , 它本质上还 是 一 个 J av a 类 , 那 么 它 就 可 以 被 继 承 或 实 现 。这个情况比较多:
示例 1:子类固定父类泛型类型(StringBox 继承自 Box<String>)
子类直接指定父类泛型参数的具体类型,适用于特定场景的扩展:
// 泛型父类
class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}
// 子类继承时指定父类泛型类型为 String
class StringBox extends Box<String> {// 新增方法:专为字符串内容设计public void toUpperCase() {String value = getContent(); // 直接使用 String 类型if (value != null) { setContent(value.toUpperCase());}}
}
public class Main {public static void main(String[] args) {StringBox box = new StringBox();box.setContent("hello");box.toUpperCase();System.out.println(box.getContent()); // 输出: HELLO}
}
关键点:
- 子类 StringBox 继承时固定了父类泛型为 String,因此 getContent() 直接返回 String 类型。
- 子类可以添加与固定类型相关的专属方法(如 toUpperCase)。
示例 2:子类保留父类泛型类型(AdvancedBox<T> 继承自 Box<T>)
子类保持父类泛型参数的灵活性,并扩展新功能:
// 父类定义不变,与示例1相同// 子类保留父类的泛型参数 <T>
class AdvancedBox<T> extends Box<T> {// 新增方法:检查内容是否为空public boolean isEmpty() {return getContent() == null;}// 新增方法:重置内容为 nullpublic void clear() {setContent(null);}
}public class Main2 {public static void main(String[] args) {AdvancedBox<Integer> intBox = new AdvancedBox<>();intBox.setContent(100);System.out.println(intBox.isEmpty()); // 输出: falseintBox.clear();System.out.println(intBox.getContent()); // 输出: null}
}
关键点:
- 子类
AdvancedBox<T>保留父类泛型参数<T>,可复用父类逻辑。 - 功能上扩展了新方法(如 isEmpty 和 clear),独立于具体类型的通用操作。
示例 3:添加子类自己的泛型参数(KeyValuePair<K,V> 继承自 Pair<K>)
父子类均使用泛型,子类引入新的类型参数:
// 泛型父类
class Pair<T> {private T first;private T second;public Pair(T first, T second) {this.first = first;this.second = second;}public T getFirst() { return first; }public T getSecond() { return second; }
}// 子类添加新的泛型参数 V,与父类参数 K 独立
class KeyValuePair<K, V> extends Pair<K> {private V value;public KeyValuePair(K key, V value) {super(key, key); // 父类需要两个同类型参数,此处复用 key 作为示例this.value = value;}// 新增方法:获取键值对的独立值public V getValue() { return value; }
}public class Main3 {public static void main(String[] args) {KeyValuePair<String, Integer> entry = new KeyValuePair<>("Age", 30);String key = entry.getFirst(); // 类型为 String(父类返回值)int value = entry.getValue(); // 类型为 Integer(子类新增方法)System.out.println(key + ": " + value); // 输出: Age: 30}
}
关键点:
- 子类
KeyValuePair<K, V>扩展了父类的泛型参数<K>,并新增了独立参数<V>。 - 父子类泛型参数独立,子类可以实现更复杂的数据结构(如键值对)。
示例 4:约束父类类型边界(IntCalculator 继承自 NumberCalculator<Integer>)
子类继承时遵循父类的泛型约束(如 <T extends Number>),并进一步具体化:
// 泛型父类,约束类型必须为 Number 的子类
class NumberCalculator<T extends Number> {protected T value;public NumberCalculator(T value) {this.value = value;}public double doubleValue() {return value.doubleValue();}
}// 子类指定父类泛型类型为 Integer
class IntCalculator extends NumberCalculator<Integer> {public IntCalculator(Integer value) {super(value);}// 新增方法:计算平方(专为 Integer 设计)public int squareInt() {return value * value;}
}public class Main4 {public static void main(String[] args) {IntCalculator calc = new IntCalculator(5);System.out.println(calc.doubleValue()); // 输出: 5.0(调用父类方法)System.out.println(calc.squareInt()); // 输出: 25(子类专属方法)}
}
关键点:
- 父类
NumberCalculator<T>的泛型参数已被约束为<T extends Number>。 - 子类
IntCalculator继承时将泛型固定为Integer,确保父类逻辑安全,同时添加Integer专用的新方法。
类型通配符
示例 1:无界通配符(<?>)
用于处理未知类型的集合,适合只读取集合内容的场景:
public class UnboundedWildcardDemo {/*** 打印任意类型集合的元素* @param list 使用无界通配符 <?>,表示接受任意类型的 List*/public static void printList(List<?> list) {for (Object item : list) {System.out.print(item + " ");}System.out.println();}public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");List<Integer> numbers = Arrays.asList(1, 2, 3);printList(names); // 输出: Alice Bob Charlie printList(numbers); // 输出: 1 2 3 }
}
关键点:
List<?>可以接受任何类型的 List,如List<String>、List<Integer>。- 只能读取元素(返回 Object),但 不能添加 元素(除了 null),因为具体类型未知。
示例 2:上界通配符(<? extends Number>)
限制类型为 Number 或其子类(如 Integer、Double),适合读取场景:
public class UpperBoundedWildcardDemo {/*** 计算数值列表的总和* @param list 使用上界通配符 <? extends Number>* @return Sum of numbers as double*/public static double sumOfList(List<? extends Number> list) {double sum = 0.0;for (Number num : list) {sum += num.doubleValue(); // 调用 Number 的方法}return sum;}public static void main(String[] args) {List<Integer> integers = Arrays.asList(1, 2, 3);List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);System.out.println(sumOfList(integers)); // 输出: 6.0System.out.println(sumOfList(doubles)); // 输出: 6.6}
}
关键点:
- 参数 list 可以接受
List<Integer>、List<Double>等(只要元素是Number的子类)。 - 不能添加元素(如 list.add(5) 会编译报错),具体子类型未知,可能破坏类型安全。
示例 3:下界通配符(<? super Integer>)
限制类型为 Integer 或其父类(如 Number、Object),适合写入场景:
public class LowerBoundedWildcardDemo {/*** 向集合中添加多个 Integer 值* @param dest 使用下界通配符 <? super Integer>,可以接受Integer或其父类(如Number、Object)的List* @param values 要添加的多个 Integer 值*/public static void addNumbersToList(List<? super Integer> dest, List<Integer> values) {dest.addAll(values); }public static void main(String[] args) {List<Number> numberList = new ArrayList<>();addNumbersToList(numberList, Arrays.asList(10, 20, 30));System.out.println(numberList); // 输出: [10, 20, 30]List<Object> objectList = new ArrayList<>();addNumbersToList(objectList, Arrays.asList(100, 200));System.out.println(objectList); // 输出: [100, 200]List<? super Integer> list = new ArrayList<Number>();list.add(1); // 允许Object obj = list.get(0); // 只能作为Object类型读取}
}
关键点:
- 参数 dest 可以是 List、List 等(父类型容器)。
- 允许添加 Integer 或其子类型的元素。
相关文章:
Java基础 - 泛型(常见用法)
文章目录 泛型类泛型方法泛型类派生子类示例 1:子类固定父类泛型类型(StringBox 继承自 Box<String>)示例 2:子类保留父类泛型类型(AdvancedBox<T> 继承自 Box<T>)示例 3:添加子类自己的…...
蓝桥杯刷题总结 + 应赛技巧
当各位小伙伴们看到这篇文章的时候想必蓝桥杯也快开赛了,那么本篇文章博主就来总结一下一些蓝桥杯的应赛技巧,那么依旧先来走个流程 那么接下来我们分成几个板块进行总结 首先是一些基本语法 编程语言的基本语法 首先是数组,在存数据的时候…...
希哈表的学习
#include <stdio.h> #include <stdlib.h> #include "uthash.h"typedef struct {int id; // 学号,作为keychar name[20]; // 姓名,作为valueUT_hash_handle hh; // 必须有这个字段 } Student;Student* studen…...
Qt之OpenGL使用Qt封装好的着色器和编译器
代码 #include "sunopengl.h"sunOpengl::sunOpengl(QWidget *parent) {}unsigned int VBO,VAO; float vertices[]{0.5f,0.5f,0.0f,0.5f,-0.5f,0.0f,-0.5f,-0.5f,0.0f,-0.5f,0.5f,0.0f };unsigned int indices[]{0,1,3,1,2,3, }; unsigned int EBO; sunOpengl::~sunO…...
备赛蓝桥杯-Python-考前突击
额,,离蓝桥杯开赛还有十个小时,最近因为考研复习节奏的问题,把蓝桥杯的优先级后置了,突然才想起来还有一个蓝桥杯呢。。 到目前为止python基本语法熟练了,再补充一些常用函数供明天考前再背背,算…...
零基础开始学习鸿蒙开发-智能家居APP离线版介绍
目录 1.我的小屋 2.查找设备 3.个人主页 前言 好久不发博文了,最近都忙于面试,忙于找工作,这段时间终于找到工作了。我对鸿蒙开发的激情依然没有减退,前几天做了一个鸿蒙的APP,现在给大家分享一下! 具体…...
不再卡顿!如何根据使用需求挑选合适的电脑内存?
电脑运行内存多大合适?在选购或升级电脑时,除了关注处理器的速度、硬盘的容量之外,内存(RAM)的大小也是决定电脑性能的一个重要因素。但究竟电脑运行内存多大才合适呢?这篇文章将帮助你理解不同使用场景下适…...
华为云 云化数据中心 CloudDC | 架构分析与应用场景
云化数据中心 CloudDC 云化数据中心 (CloudDC)是一种满足传统DC客户云化转型诉求的产品,支持将客户持有服务器设备部署至华为云机房,通过外溢华为云的基础设施管理、云化网络、裸机纳管、确定性运维等能力,帮助客户DC快速云化转型。 云化数据…...
【射频仿真学习笔记】变压器参数的Mathematica计算以及ADS仿真建模
变压器模型理论分析 对于任意的无源电路或者等效电路,当画完原理图后,能否认为已经知道其中的两个节点?vin和vout之间的明确解析解 是否存在一个通用的算法,将这里的所有元素都变成了符号,使得这个算法本身就是一个函…...
Linux系统Docker部署开源在线协作笔记Trilium Notes与远程访问详细教程
今天和大家分享一款在 G 站获得了 26K的强大的开源在线协作笔记软件,Trilium Notes 的中文版如何在 Linux 环境使用 docker 本地部署,并结合 cpolar 内网穿透工具配置公网地址,轻松实现远程在线协作的详细教程。 Trilium Notes 是…...
C++基础精讲-01
1C概述 1.1初识C 发展历程: C 由本贾尼・斯特劳斯特卢普在 20 世纪 70 年代开发,它在 C 语言的基础上增加了面向对象编程的特性,最初被称为 “C with Classes”,后来逐渐发展成为独立的 C 语言。 语言特点 (1&#x…...
为什么Java不支持多继承?如何实现多继承?
一、前言 Java不支持多继承(一个类继承多个父类)主要出于文中设计考虑;核心目的是简化语言复杂性并避免潜在的歧义性问题。 二、直接原因:菱形继承/钻石继承问题(Diamond Problem) 假设存在如下继承关系&…...
E8流程多行明细行字符串用I分隔,赋值到主表
需求:明细行摘要字段赋值到主表隐藏字段,隐藏摘要字段在标题中显示 代码如下,代码中的获取字段名获取方式,自行转换成jQuery("#fieldid").val()替换。 //1:参数表单id 2:流程字段名 3:0代表主表,1代表明细…...
QML面试笔记--UI设计篇04交互控件
1. QML中常用交互控件 1.1. Button1.2. Slider1.3. ProgressBar1.4. TextField1.5. TextArea1.6. ComboBox1.7. CheckBox1.8. RadioButton1.9. Menu1.10. Dialog 1. QML中常用交互控件 在万物互联的智能时代,QML凭借其声明式语法和跨平台能力,…...
[特殊字符] Spring Boot 日志系统入门博客大纲(适合初学者)
一、前言 📌 为什么日志在项目中如此重要? 在开发和维护一个后端系统时,日志就像程序运行时的“黑匣子”,帮我们记录系统的各种行为和异常。一份良好的日志,不仅能帮助我们快速定位问题,还能在以下场景中…...
【人工智能】AI大模型开发数学基础指南
目录 学习内容**1. 线性代数****2. 概率与统计****3. 微积分****4. 优化理论****5. 信息论****6. 数值计算****7. 离散数学****8. 统计学进阶****如何学习?****总结** 如何学习**1. 明确学习目标****2. 分阶段学习计划****阶段 1:夯实基础****阶段 2&…...
Express中间件(Middleware)详解:从零开始掌握(1)
1. 中间件是什么? 想象中间件就像一个"加工流水线",请求(Request)从进入服务器到返回响应(Response)的过程中,会经过一个个"工作站"进行处理。 简单定义:中间件是能够访问请求对象(req)、响应对象(res)和下…...
STM32单片机中EXTI的工作原理
目录 1. EXTI概述 2. EXTI的组成部分 3. 工作原理 3.1 引脚配置 3.2 中断触发条件 3.3 中断使能 3.4 中断处理 4. 使用示例 5. 注意事项 结论 在STM32单片机中,EXTI(外部中断)是一种用于处理外部事件的机制,能够提高对硬…...
现代工业测试的核心支柱:电机试验工作台?(北重机械厂家)
电机试验工作台是现代工业测试中的核心支柱之一。这种工作台通常用于对各种类型的电机进行性能测试、负载测试和耐久性测试。通过电机试验工作台,工程师可以评估电机的效率、功率输出、转速、扭矩、温度等关键参数,从而确保电机的设计符合要求࿰…...
oracle 11g密码长度和复杂度查看与设置
verify_function_11G 的密码复杂性要求: 密码长度至少为 8 个字符。 密码必须包含至少一个数字和一个字母字符。 密码不能与用户名相同或相似。 密码不能是服务器名或其变体。 密码不能是常见的弱密码(如 welcome1、oracle123 等)。 注意事项&…...
CVE-2025-32375 | Windows下复现 BentoML runner 服务器远程命令执行漏洞
目录 1. 漏洞描述2. 漏洞复现1. 安装 BentoML 1.4.72. 创建模型3. 构建模型4. 托管模型5. 执行exp 3. POC4. 补充学习 参考链接: https://mp.weixin.qq.com/s/IxLZr83RvYqfZ_eXhtNvgg https://github.com/bentoml/BentoML/security/advisories/GHSA-7v4r-c989-xh26 …...
某局jsvmp算法分析(dunshan.js/lzkqow23819/lzkqow39189)
帮朋友看一个税某局的加密算法。 传送门 (需要帐号登陆的 普通人没授权也看不了) 废话不多说直接抓包开干 这里可以看到一个headers中的加密参数 lzkqow23819 以及url路径里面的6eMrZlPH(这个有点像瑞数里面的) 还有就是cookies里面的这几个…...
深入剖析 Kafka 的零拷贝原理:从操作系统到 Java 实践
Kafka 作为一款高性能的分布式消息系统,其卓越的吞吐量和低延迟特性得益于多种优化技术,其中“零拷贝”(Zero-Copy)是核心之一。零拷贝通过减少用户态与内核态之间的数据拷贝,提升了 Kafka 在消息传输中的效率。本文将…...
AlmaLinux9.5 修改为静态IP地址
查看当前需要修改的网卡名称 ip a进入网卡目录 cd /etc/NetworkManager/system-connections找到对应网卡配置文件进行修改 修改配置 主要修改ipv4部分,改成自己的IP配置 [ipv4] methodmanual address1192.168.252.129/24,192.168.252.254 dns8.8.8.8重启网卡 …...
内联函数通常定义在头文件中的原因详解
什么是内联函数? 内联函数(inline function)是C中的一种函数优化机制,通过在函数声明前加上inline关键字,建议编译器将函数调用替换为函数体本身的代码,从而减少函数调用的开销。 为什么内联函数需要定义…...
操作系统 4.4-从生磁盘到文件
文件介绍 操作系统中对磁盘使用的第三层抽象——文件。这一层抽象建立在盘块(block)和文件(file)之间,使得用户可以以更直观和易于理解的方式与磁盘交互,而无需直接处理磁盘的物理细节如扇区(se…...
免费多语言文档翻译软件推荐
软件介绍 今天给大家介绍一款文档翻译助手。它能够支持PDF、Word等多种文档格式,涵盖中文、英文、日语等多语言互译。此软件在翻译过程中精选保留文档原貌,每段文字、每个图表的匹配都十分完美,还依托顶尖翻译大模型,让翻译结果符…...
安全序列(DP)
#include <bits/stdc.h> using namespace std; const int MOD1e97; const int N1e65; int f[N]; int main() {int n,k;cin>>n>>k;f[0]1;for(int i1;i<n;i){f[i]f[i-1]; // 不放桶:延续前一位的所有方案if(i-k-1>0){f[i](f[i]f[i-k…...
【Flask开发】嘿马文学web完整flask项目第4篇:4.分类,4.分类【附代码文档】
教程总体简介:2. 目标 1.1产品与开发 1.2环境配置 1.3 运行方式 1.4目录说明 1.5数据库设计 2.用户认证 Json Web Token(JWT) 3.书架 4.1分类列表 5.搜索 5.3搜索-精准&高匹配&推荐 6.小说 6.4推荐-同类热门推荐 7.浏览记录 8.1配置-阅读偏好 8.配置 9.1项目…...
SQL开发的智能助手:通义灵码在IntelliJ IDEA中的应用
SQL 是一种至关重要的数据库操作语言,尽管其语法与通用编程语言有所不同,但因其在众多应用中的广泛使用,大多数程序员都具备一定的 SQL 编写能力。然而,当面对复杂的 SQL 语句或优化需求时,往往需要专业数据库开发工程…...
