Java中泛型的详细介绍
引言:
Java语言中的泛型是一种强大的特性,它允许我们在编写代码时指定类、接口和方法的参数类型。通过使用泛型,我们可以提高代码的重用性、可读性和安全性。在本博客中,我们将详细介绍Java中泛型的知识。
一、泛型的基本概念
泛型是Java 5中引入的一个新特性。它的核心思想是参数化类型,即允许在创建类、接口和方法时使用参数来代替具体的类型。这样一来,使用泛型的代码可以适应不同的数据类型,提高代码的灵活性。
二、泛型类与泛型接口
1、定义泛型类
在泛型类中,我们可以使用泛型来代替具体的类型。例如,我们可以创建一个泛型类Box<T>,其中T表示类型参数,可以是任意合法的Java类型。定义泛型类的语法如下:
public class Box<T> {private T value;public void setValue(T value) {this.value = value;}public T getValue() {return value;}
}
在使用泛型类时,我们可以通过实例化时指定类型参数的方式创建对象:
Box<Integer> box = new Box<>();
box.setValue(10);
Integer value = box.getValue();
通过这种方式,我们可以使用Box类来存储不同类型的对象,而无需创建多个不同的类。
2、定义泛型接口
与泛型类类似,我们也可以定义泛型接口。例如,我们可以创建一个泛型接口List<T>,其中T表示类型参数。定义泛型接口的语法如下:
public interface List<T> {void add(T element);T get(int index);
}
在实现泛型接口时,我们可以指定具体的类型参数:
public class ArrayList<T> implements List<T> {// 省略实现
}
三、泛型方法
除了泛型类和泛型接口,Java还支持泛型方法。我们可以在方法声明中使用类型参数,从而使该方法可以接受不同的参数类型。定义泛型方法的语法如下:
public <T> void printArray(T[] array) {for (T element : array) {System.out.println(element);}
}
在调用泛型方法时,编译器会根据参数的类型推断出相应的类型参数:
Integer[] numbers = {1, 2, 3, 4, 5};
printArray(numbers);String[] names = {"Alice", "Bob", "Charlie"};
printArray(names);
四、通配符
在使用泛型时,有时我们需要限制类型参数的范围。Java提供了通配符(Wildcard)来实现这个目的。通配符分为无界通配符"?“和有界通配符”?"。
1、无界通配符(Unbounded Wildcard)
无界通配符表示可以是任意类型,使用"?"表示。例如,List<?>表示一个不确定类型的列表。无界通配符通常用于处理一些与类型无关的操作。
2、有界通配符(Bounded Wildcard)
有界通配符用来限制类型参数的范围,可以是上界(Upper Bounded)或下界(Lower Bounded)。例如,List<? extends Number>表示一个元素为任意Number类型或其子类的列表。有界通配符通常用于处理一些与特定类型相关的操作。
五、泛型类型的类型擦除
在编译期间,Java对泛型做了类型擦除。也就是说,泛型类型的参数信息在运行时是不可用的。这意味着无法在运行时获取泛型类型的具体参数。
六、泛型的优点与缺点
1、优点
- 提高代码的重用性:通过泛型,我们可以编写与特定类型无关的通用代码,从而提高代码的重用性。
- 增强代码的可读性:使用泛型可以使代码更加清晰和易读,因为类型参数提供了对代码的更好的描述。
- 提高代码的安全性:泛型可以在编译时捕获一些类型错误,从而减少在运行时出现类型转换错误的可能性。
- 避免了强制类型转换:在使用非泛型的旧代码中,我们经常需要进行强制类型转换,而泛型可以避免这种情况的发生。
2、缺点
- 无法使用基本数据类型作为类型参数:由于类型擦除的原因,无法使用基本数据类型(例如int、char等)作为泛型类型的参数。需要使用对应的包装类(如Integer、Character)来代替。
- 泛型信息在运行时不可用:在泛型代码中,类型参数的具体信息在运行时是无法获得的,这可能导致一些限制和不便。
七、泛型在集合框架中的应用
Java集合框架中广泛使用了泛型,使得我们可以更安全和方便地操作和管理数据集合。例如,List<E>、Set<E>和Map<K, V>等接口和类都使用泛型来指定其元素类型或键值对类型。
八、泛型的一些常见用法
1、定义泛型类、接口和方法:通过使用类型参数来实现通用代码和数据结构。
泛型类:
public class Box<T> {private T item;public void setItem(T item) {this.item = item;}public T getItem() {return item;}
}// 使用泛型类
Box<Integer> integerBox = new Box<Integer>();
integerBox.setItem(10);
Integer value = integerBox.getItem(); // 返回 10Box<String> stringBox = new Box<String>();
stringBox.setItem("Hello");
String message = stringBox.getItem(); // 返回 "Hello"
泛型接口:
public interface List<T> {void add(T item);T get(int index);
}// 实现泛型接口
public class ArrayList<T> implements List<T> {private T[] array;public ArrayList() {array = (T[]) new Object[10];}@Overridepublic void add(T item) {// 添加元素到数组}@Overridepublic T get(int index) {// 获取指定位置的元素return array[index];}
}
泛型方法:
public <T> T getMax(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if (array[i].compareTo(max) > 0) {max = array[i];}}return max;
}// 使用泛型方法
Integer[] numbers = {5, 10, 3, 8};
Integer maxNumber = getMax(numbers); // 返回 10String[] names = {"Alice", "Bob", "Caroline"};
String maxName = getMax(names); // 返回 "Caroline"
2、使用通配符扩展泛型类型的范围:通过使用extends关键字限制类型参数的上界,或使用super关键字限制类型参数的下界。
限制类型参数的上界(extends):
public void processList(List<? extends Number> list) {// 可以读取列表中的元素,因为列表中的元素都是Number或Number的子类for (Number num : list) {// 处理元素}
}List<Integer> integers = new ArrayList<>();
integers.add(10);
integers.add(20);
processList(integers);List<Double> doubles = new ArrayList<>();
doubles.add(3.14);
doubles.add(2.718);
processList(doubles);
限制类型参数的下界(super):
public void addNumbers(List<? super Integer> list) {// 可以向列表中添加Integer类型的元素,因为列表中的元素类型是Integer或Integer的父类list.add(10);list.add(20);
}List<Number> numbers = new ArrayList<>();
numbers.add(3.14);
addNumbers(numbers);List<Object> objects = new ArrayList<>();
objects.add("Hello");
addNumbers(objects);
3、泛型类型的参数和返回值:可以将泛型类型作为方法的参数和返回值,从而实现对不同类型的支持。
public class GenericExample {// 泛型类型参数作为方法参数public static <T> void printArray(T[] array) {for (T element : array) {System.out.print(element + " ");}System.out.println();}// 泛型类型参数作为方法返回值public static <T> T getFirstElement(T[] array) {if (array != null && array.length > 0) {return array[0];} else {return null;}}public static void main(String[] args) {Integer[] intArray = {1, 2, 3, 4, 5};String[] strArray = {"Hello", "World"};// 使用泛型类型参数作为方法参数printArray(intArray);printArray(strArray);// 使用泛型类型参数作为方法返回值Integer firstInt = getFirstElement(intArray);String firstStr = getFirstElement(strArray);System.out.println("First integer: " + firstInt);System.out.println("First string: " + firstStr);}
}
上述示例中的printArray方法使用了泛型类型参数T[]作为参数,可以接受任意类型的数组,并打印数组中的元素。
getFirstElement方法则使用了泛型类型参数T作为返回值,它返回数组的第一个元素。根据传入的具体数组类型,返回对应类型的元素。
在main方法中,我们分别使用了Integer和String类型的数组来演示这两个方法的使用。
总结:
本博客详细介绍了Java中泛型的知识,包括泛型的基本概念、泛型类与泛型接口、泛型方法、通配符、泛型类型的类型擦除等内容。同时,还介绍了泛型在集合框架中的应用以及一些常见的泛型用法。通过学习和应用泛型,我们可以提高代码的重用性、可读性和安全性,使我们的代码更具灵活性和扩展性。
相关文章:
Java中泛型的详细介绍
引言: Java语言中的泛型是一种强大的特性,它允许我们在编写代码时指定类、接口和方法的参数类型。通过使用泛型,我们可以提高代码的重用性、可读性和安全性。在本博客中,我们将详细介绍Java中泛型的知识。 一、泛型的基本概念 泛型…...
chrome 307状态码
问题:不知道什么原因导致http请求chrome始终307跳转到https,这个307的跳转非常恶心的地方是客户端缓存行为,并且非普通的f12下面清除缓存可以去掉 解决办法:使用chrome的清除浏览数据,通过这个方式清除,才能解决。 问…...
Redis在Windows10中安装和配置
1.首先去下载Redis 这里不给出下载地址,自己可以用去搜索一下地址 下载 下载完成后解压到D盘redis下,本人用的是3.2.100 D:\Redis\Redis-x64-3.2.100 2.解压完成后需要设置环境变量,这里新建一个系统环境变量中path 中添加一个文件所…...
华为OD机试 - 特殊的加密算法(Java JS Python C)
题目描述 有一种特殊的加密算法,明文为一段数字串,经过密码本查找转换,生成另一段密文数字串。 规则如下: 明文为一段数字串由 0~9 组成密码本为数字 0~9 组成的二维数组需要按明文串的数字顺序在密码本里找到同样的数字串,密码本里的数字串是由相邻的单元格数字组成,上…...
MySQL——性能优化与关系型数据库
文章目录 什么是性能?什么是关系型数据库?数据库设计范式 常见的数据库SQL语言结构化查询语言的六个部分版本 MySQL数据库故事历史版本5.6/5.7差异5.7/8.0差异 什么是性能? 吞吐与延迟:有些结论是反直觉的,指导我们关…...
【机器学习300问】12、为什么要进行特征归一化?
当线性回归模型的特征量变多之后,会出现不同的特征量,然而对于那些同是数值型的特征量为什么要做归一化处理呢? 一、为了消除数据特征之间的量纲影响 使得不同指标之间具有可比性。例如,分析一个人的身高和体重对健康的影响&…...
CSV文件中json列的处理2
如上所示,csv文件中包含以中括号{}包含的json字段,可用如下方法提取: import pandas as pd from datetime import date todaystr(date.today()) import jsonfilepath/Users/kangyongqing/Documents/kangyq/202401/调课功能使用统计/ file104…...
eNSP学习——部分VLAN间互通、部分VLAN间隔离、VLAN内用户隔离(MUX-VLAN)
MUX VLAN(Multiplex VLAN)提供了一种通过VLAN进行网络资源控制 的机制。通过MUX VLAN提供的二层流量隔离的机制可以实现企业内部员 工之间互相通信,而企业外来访客之间的互访是隔离的。 特点: 一、主VLAN端口可以和所有VLAN通信 二…...
【音视频】如何播放rtsp视频流
背景 现阶段直播越来越流行,直播技术发展也越来越快。Webrtc和rtsp是比较火热的技术,而且应用也比较广泛。本文通过实践来展开介绍关于rtsp、webrtc的使用过程。 概要 本文重点介绍如何播放rtsp视频流,通过ffplay方式以及VLC media player…...
Qt6入门教程 8:信号和槽机制(连接方式)
目录 一.一个信号与槽连接的例子 二.第五个参数 1.Qt::AutoConnection 2.Qt::DirectConnection 3.Qt::QueuedConnection 4.Qt::BlockingQueuedConnection 5.Qt::UniqueConnection 三.信号 四.connect函数原型 五.信号与槽的多种用法 六.槽的属性 一.一个信号与槽连接…...
Python如何操作RabbitMQ实现fanout发布订阅模式?有录播直播私教课视频教程
fanout发布订阅模式 基本用法 生产者 import json import rabbitmq# 建立连接 credentials rabbitmq.PlainCredentials(zhangdapeng,zhangdapeng520, ) # mq用户名和密码 connection_target rabbitmq.ConnectionParameters(host127.0.0.1,port5672,virtual_host/,credent…...
QT 原生布局和QML的区别
一、QML 与 Qt Quick的区别 1.1 从概念上区分 为了更精确地对两者进行说明,先看助手对 QML 的描述: QML is a user interface specification and programming language. QML 是一种用户界面规范和标记语言,允许开发人员和设计师创建高性能、流…...
视频转码实例:把MP4转为MKV视频,一键批量转换的操作方法
在数字媒体时代,视频格式的多样性是不可避免的。经常把MP4格式的视频转换为MKV格式。MKV格式有较高的音频和视频质量,能在其他设备或软件上播放视频。以下是云炫AI智剪如何把MP4视频转为MKV格式的一键批量转换操作方法。 已转码的mkv视频效果缩略图展示…...
异步Merkle Tree
1. 引言 前序博客: 利用多核的Rust快速Merkle tree Anoushk Kharangate 2023年论文《Asynchronous Merkle Trees》,其对Merkle tree数据结构进行修改,使得可跨多线程异步计算。 开源代码实现见: https://github.com/anoushk1…...
7. UE5 RPG修改GAS的Attribute的值
前面几节文章介绍了如何在角色身上添加AbilitySystemComponent和AttributeSet。并且还实现了给AttributeSet添加自定义属性。接下来,实现一下如何去修改角色身上的Attribute的值。 实现拾取药瓶回血功能 首先创建一个继承于Actor的c类,actor是可以放置到…...
Oracle/DM序列基本使用
序列(SEQUENCE)是序列号生成器,可以为表中的行自动生成序列号,产生一组等间隔的数值(类型为数字)。其主要的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一个值。序列是一个计…...
校验ChatGPT 4真实性的三个经典问题:提供免费测试网站快速区分 GPT3.5 与 GPT4
现在已经有很多 ChatGPT 的套壳网站,以下分享验明 GPT-4 真身的三个经典问题,帮助你快速区分套壳网站背后到底用的是 GPT-3.5 还是 GPT-4。 大家可以在这个网站测试:https://ai.hxkj.vip,免登录可以问三条,登录之后无限…...
概率论与数理统计————3.随机变量及其分布
一、随机变量 设E是一个随机试验,S为样本空间,样本空间的任意样本点e可以通过特定的对应法则X,使得每个样本点都有与之对应的数对应,则称XX(e)为随机变量 二、分布函数 分布函数:设X为随机变量…...
掌握单例模式的极致挑战:能否默写饿汉式代码?
目录 1.前言 2.本质 3.代码默写 1.前言 在面试中,理解和掌握单例模式是非常重要的。本文旨在帮助读者深入理解饿汉式单例模式,并通过简洁明了的解释和示例代码,使读者能够轻松掌握并默写出饿汉式单例模式的代码实现。 2.本质 饿汉式单例模…...
力扣刷MySQL-第三弹(详细讲解)
🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:力扣刷题讲解-MySQL 🍹文章作者技术和水平很有限,如果文中出…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...
