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

深入解析Java泛型:从定义到实战应用

目录

  • 🚀前言
  • 🤔泛型的定义
  • 🐧泛型类
  • 🌟泛型接口
  • ✍️泛型方法、通配符、上下限
    • 💯泛型方法
    • 💯 通配符与上下限
      • ⚙️通配符(Wildcard)
      • ⚙️泛型上下限
      • ⚙️应用场景
  • 🦜泛型支持的类型
      • ⚙️泛型擦除
    • 💯包装类
      • ⚙️自动装箱与自动拆箱
      • ⚙️常用功能
      • ⚙️应用场景

🚀前言

在这里插入图片描述

大家好!我是 EnigmaCoder
本文主要介绍java泛型部分,包含泛型的定义、泛型类、泛型接口、泛型方法、通配符、上下限等。

🤔泛型的定义

定义类、接口、方法时,同时声明了一个或者多个类型变量(如:<E>,则称为泛型类、泛型接口、泛型方法,它们统称为泛型。

例如

public class ArrayList<E>{...
}

作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力。这样可以避免强制类型转换,及其可能出现的异常。

代码示例

public class Test {public static void main(String[] args) {ArrayList <String>list = new ArrayList<String>();list.add("hello");list.add("world");list.add(23);for(String str:list){System.out.println(str);}}
}
  • 由于使用了泛型,这段代码中list.add(23);会报错,只能使用String类型。如果不使用泛型,则遍历时需要进行强制类型转换,容易出现异常。
  • 泛型的本质:把具体的数据类型作为参数传给类型变量。

🐧泛型类

在Java中,泛型类是一种可以操作多种数据类型的类,它通过类型参数化来实现代码的复用和类型安全。泛型类的定义格式如下:

修饰符 class 类名<类型变量,类型变量,...>{
}

注意:类型变量建议用大写的英文字母,常用的有:E、T、K、V等。

代码示例

public class Box<T> {private T item;public void setItem(T item) {this.item = item;}public T getItem() {return item;}
}
  • Box是一个泛型类,类型参数为T
  • itemBox类的一个私有成员变量,类型为T
  • setItem方法用于设置item的值,参数类型为T
  • getItem方法用于获取item的值,返回类型为T

使用场景

泛型类在需要处理多种数据类型时非常有用,特别是在集合类中。例如,Java标准库中的ArrayListHashMap等都是泛型类。通过使用泛型类,可以避免类型转换的麻烦,并提高代码的类型安全性。

🌟泛型接口

Java中,泛型接口是一种允许在接口定义中使用类型参数的机制。通过使用泛型接口,可以创建更加灵活和可重用的代码,因为它允许接口方法操作多种类型的数据,而不需要为每种类型都编写一个单独的接口。

格式如下

修饰符 interface 接口<类型变量,类型变量...>{...
}

注意:同样建议使用大写英文字母,如:E、T、K、V等。

代码示例

public interface Box<T> {void add(T item);T get();
}
public class StringBox implements Box<String> {private String item;@Overridepublic void add(String item) {this.item = item;}@Overridepublic String get() {return item;}
}
  • 在这个例子中,StringBox类实现了Box接口,并指定类型参数为String。因此,add方法接受一个String类型的参数,get方法返回一个String类型的值。
  • 泛型接口是Java中一种强大的工具,它允许开发者编写更加通用和可重用的代码。通过使用泛型接口,可以避免为每种数据类型编写单独的接口,从而提高代码的灵活性和可维护性。在实际开发中,泛型接口广泛应用于集合框架、回调机制、数据存储等场景。

✍️泛型方法、通配符、上下限

💯泛型方法

泛型方法是Java中一种强大的特性,它允许在方法中使用类型参数,从而使方法能够处理多种类型的数据,而不需要为每种类型编写单独的方法。泛型方法在集合框架、工具类等场景中广泛应用,能够提高代码的复用性和类型安全性。

格式如下

修饰符<类型变量,类型变量,...>返回值类型 方法名(形参列表){...
}

代码示例

public class GenericMethodExample {// 定义一个泛型方法public static <T> void printValue(T value) {System.out.println("Value: " + value);}public static void main(String[] args) {// 调用泛型方法,传入不同类型的参数printValue("Hello, World!");  // 输出: Value: Hello, World!printValue(123);              // 输出: Value: 123printValue(3.14);             // 输出: Value: 3.14}
}

💯 通配符与上下限

Java泛型编程中,通配符和上下限是处理泛型类型的重要概念,它们提供了更灵活的类型处理方式。

⚙️通配符(Wildcard)

通配符用“?”表示,它可以在使用泛型时代表任意类型。通配符通常用于泛型方法的参数类型或泛型类的类型参数中,以增加代码的灵活性。例如,在定义一个方法时,如果希望该方法能够接受任何类型的List,可以使用通配符:

public void printList(List<?> list) {for (Object elem : list) {System.out.println(elem);}
}

在这个例子中,List<?>表示可以接受任何类型的List,无论是List<String>List<Integer>还是其他类型的List。

⚙️泛型上下限

泛型上下限用于限制泛型类型的范围,使得泛型类型更加安全和可控。

  • 泛型上限(Upper Bound

泛型上限使用? extends T表示,其中T是一个具体的类或接口。它表示泛型类型必须是T或其子类。例如:

public void processCars(List<? extends Car> cars) {for (Car car : cars) {car.drive();}
}

在这个例子中,List<? extends Car>表示cars列表中的元素必须是Car类或其子类(如SportsCarSUV)。这样可以确保在processCars方法中,所有元素都至少具有Car类的方法。

  • 泛型下限(Lower Bound

泛型下限使用? super T表示,其中T是一个具体的类或接口。它表示泛型类型必须是T或其父类。例如:

public void addCar(List<? super Car> cars, Car car) {cars.add(car);
}

在这个例子中,List<? super Car>表示cars列表中的元素必须是Car类或其父类(如Vehicle)。这样可以确保在addCar方法中,可以向列表中添加Car对象或其子类对象。

⚙️应用场景

  • 通配符:适用于需要处理多种类型但不需要知道具体类型的场景,如通用的集合处理方法。
  • 泛型上限:适用于需要限制类型为某个类或其子类的场景,如处理特定类及其子类的集合。
  • 泛型下限:适用于需要限制类型为某个类或其父类的场景,如向集合中添加特定类或其子类的对象。

通过合理使用通配符和泛型上下限,可以使泛型代码更加灵活、安全和易于维护。

🦜泛型支持的类型

在Java中,泛型是一种强大的特性,它允许在定义类、接口和方法时使用类型参数。然而,泛型有一个重要的限制:它不支持基本数据类型(如int、char、boolean等),只能支持对象类型(即引用数据类型,如Integer、String、List等)。这是因为泛型的实现机制依赖于Java的类型系统,而基本数据类型并不属于对象类型。

⚙️泛型擦除

  • 泛型在Java中的实现是通过一种称为“泛型擦除”的机制来完成的。泛型擦除意味着泛型信息只在编译阶段有效,而在编译后的字节码中,所有的泛型类型参数都会被替换为它们的上界(通常是Object类型)。因此,在运行时,泛型类型信息是不可用的。例如,List<String>在编译后会被擦除为List<Object>,这意味着在运行时,你无法通过反射等方式获取到List中元素的类型信息。

  • 这种设计的主要目的是为了保持与Java早期版本的兼容性,因为泛型是在Java 5中引入的,而在此之前,Java的集合类都是使用Object类型来存储元素的。

💯包装类

由于泛型不支持基本数据类型,Java提供了包装类(Wrapper Classes)来将基本数据类型包装成对象类型。包装类位于java.lang包中,每个基本数据类型都有对应的包装类,例如Integer对应intDouble对应doubleBoolean对应boolean等。

基本数据类型包装类默认值字节数最小值最大值
byteByte01-128127
shortShort02-32,76832,767
intInteger04-2,147,483,6482,147,483,647
longLong0L8-9,223,372,036,854,775,8089,223,372,036,854,775,807
floatFloat0.0F41.4E-453.4028235E38
doubleDouble0.0D84.9E-3241.7976931348623157E308
charCharacter'\u0000'2'\u0000' (0)'\uffff' (65,535)
booleanBooleanfalse-falsetrue

⚙️自动装箱与自动拆箱

Java 5引入了自动装箱(Autoboxing)和自动拆箱(Unboxing)机制,使得基本数据类型和它们的包装类之间的转换更加方便。

  • 自动装箱:当需要将一个基本数据类型赋值给一个包装类对象时,Java会自动将基本数据类型转换为对应的包装类对象。例如:

    Integer i = 10;  // 自动装箱,int 10 被转换为 Integer 对象
    
  • 自动拆箱:当需要将一个包装类对象赋值给一个基本数据类型变量时,Java会自动将包装类对象转换为对应的基本数据类型。例如:

    int j = i;  // 自动拆箱,Integer 对象 i 被转换为 int 类型
    

⚙️常用功能

包装类不仅提供了基本数据类型与对象类型之间的转换功能,还提供了一些常用的实用方法:

  1. 将基本数据类型转换为字符串:每个包装类都提供了toString()方法,可以将基本数据类型的数据转换为字符串。例如:

    int num = 123;
    String str = Integer.toString(num);  // 将 int 转换为字符串 "123"
    
  2. 将字符串转换为基本数据类型:包装类还提供了parseXxx()方法,可以将字符串类型的数值转换为对应的基本数据类型。例如:

    String str = "456";
    int num = Integer.parseInt(str);  // 将字符串 "456" 转换为 int 类型
    
  3. 其他实用方法:包装类还提供了一些其他实用方法,如valueOf()compareTo()equals()等,用于处理基本数据类型的比较、转换等操作。

⚙️应用场景

包装类在Java编程中有着广泛的应用,特别是在需要使用泛型或集合类时。例如,当你需要在List中存储整数时,由于泛型不支持基本数据类型,你必须使用Integer包装类:

List<Integer> numbers = new ArrayList<>();
numbers.add(10);  // 自动装箱,int 10 被转换为 Integer 对象
int firstNumber = numbers.get(0);  // 自动拆箱,Integer 对象被转换为 int 类型

此外,包装类在处理数据库操作、网络通信等场景中也经常被使用,因为这些场景通常需要将数据以对象的形式进行传递和处理。

通过使用包装类,Java程序员可以更加灵活地处理基本数据类型和对象类型之间的转换,从而编写出更加健壮和可维护的代码。

相关文章:

深入解析Java泛型:从定义到实战应用

目录 &#x1f680;前言&#x1f914;泛型的定义&#x1f427;泛型类&#x1f31f;泛型接口✍️泛型方法、通配符、上下限&#x1f4af;泛型方法&#x1f4af; 通配符与上下限⚙️通配符&#xff08;Wildcard&#xff09;⚙️泛型上下限⚙️应用场景 &#x1f99c;泛型支持的类…...

【开源】一个基于 Vue3 和 Electron 开发的第三方网易云音乐客户端,具有与官方客户端相似的界面布局

&#x1f3b5; XCMusic&#xff1a;高颜值第三方网易云音乐客户端 &#x1f3b6; &#x1f4cd; 项目亮点 XCMusic 是一款基于Vue3Electron开发的开源、跨平台网易云音乐客户端。 此音乐播放器基于 Electron 开发&#xff0c;旨在为用户提供简洁、美观、兼容多平台的音乐体验。…...

【云实验】Excel文件转存到RDS数据库

实验名称&#xff1a;Excel文件转存到RDS数据库 说明&#xff1a;把Excel的数据通过数据管理服务DMS&#xff08;Data Management Service&#xff09;导入到RDS MySQL数据库中。 流程&#xff1a;创建一个RDS for MySQL的实例&#xff0c;再创建数据库和账号&#xff0c;通过D…...

从零开始:用Python语言基础构建宠物养成游戏:从核心知识到完整实战

一、代码分段拆解与知识点映射 1. 初始化游戏数据&#xff1a;变量与数据类型的综合应用 # 用字典存储宠物信息&#xff08;嵌套字典数字/字符串类型&#xff09; pet {"name": "小雪", # 字符串&#xff1a;宠物名字"age": 1, …...

labview设计一个虚拟信号发生器

目标&#xff1a;设计一个虚拟信号发生器&#xff0c;通过功能键的设置可以产生正弦波、三角波、方波和锯齿波&#xff0c;并可以通过输入控件设置采集信号的频率、幅值、相位等参数。 一、正弦波 &#xff08;1&#xff09;创建一个枚举 &#xff08;2&#xff09;点击属性后…...

工业路由器WiFi6+5G的作用与使用指南,和普通路由器对比

工业路由器的技术优势 在现代工业环境中&#xff0c;网络连接的可靠性与效率直接影响生产效率和数据处理能力。WiFi 6&#xff08;即802.11ax&#xff09;和5G技术的结合&#xff0c;为工业路由器注入了强大的性能&#xff0c;使其成为智能制造、物联网和边缘计算的理想选择。…...

Chrome 插件网络请求的全面指南

在 Chrome 插件开发中&#xff0c;网络请求可以在多个上下文中实现&#xff0c;而不仅限于 background.js 和 content.js。以下是完整的网络请求实现方案&#xff1a; 一、主要请求实现位置 1. Background Script (后台脚本) 特点&#xff1a; 生命周期最长适合处理敏感数据…...

编译Qt5.15.16并启用pdf模块

编译Qt5.15.16并启用pdf模块 标题1.目录设置 -q-bulid –qt-everywhere-src-5.15.16 –bulid cd bulid 必须&#xff0c;否则会提示Project ERROR: You cannot configure qt separately within a top-level build. create .qmake.stash and .qmake.super in build folder …...

Python绘制新冠疫情的知识图谱

from pyvis.network import Network import networkx as nx import pandas as pd import os# 修复模板路径 from pyvis import network as net_moduleos.environ["PATH"] os.pathsep os.path.dirname(net_module.__file__)# 创建紧密连接图 g nx.Graph()# 关键修…...

canvas(三)-动画3d

在 <canvas> 中实现 3D 动画通常需要借助 WebGL 技术&#xff0c;因为原生的 2D 上下文&#xff08;CanvasRenderingContext2D&#xff09;无法直接支持 3D 渲染。WebGL 是基于 OpenGL ES 2.0 的 JavaScript API&#xff0c;可以直接在浏览器中实现高性能的 3D 图形渲染。…...

使用RUST在Arduino上进行编程(MacOS,mega板)

近年来&#xff0c;RUST成为了嵌入式编程的热门语言&#xff0c;本文通过实现&#xff08;1&#xff09;LED闪灯&#xff0c;以及&#xff08;2&#xff09;在console&#xff08;终端&#xff09;实现“Hello Rust World”两项功能来完成实操的入门。 深入学习可以参考RUST语言…...

MySQL迁移SSL报错

文章记录了之前tdsql迁移IDC过程中遇到的小问题 环境 xboss业务&#xff1a; tdsql未启用SSL&#xff0c; IDC-mysql启用了SSL: 原因分析 1&#xff0c; 迁移前&#xff1a; 因为tdsql未启用ssl&#xff0c; 且应用未显式配置ssl JDBC默认使用非SSL连接&#xff0c;因此可以正…...

大模型微调与高效训练

随着预训练大模型(如BERT、GPT、ViT、LLaMA、CLIP等)的崛起,人工智能进入了一个新的范式:预训练-微调(Pre-train, Fine-tune)。这些大模型在海量数据上学习到了通用的、强大的表示能力和世界知识。然而,要将这些通用模型应用于特定的下游任务或领域,通常还需要进行微调…...

LLM驱动的未来软件工程范式与架构策略

历史回顾与范式奠基 软件工程自其诞生以来,经历了数次里程碑式的范式变革。最初的汇编语言时代,程序员与机器指令直接对话,效率低下,代码难以复用。随后,高级语言(如Fortran、C)的出现,通过抽象层极大地提升了开发效率,并催生了面向过程的编程范式。进入20世纪末,面…...

OpenCv高阶(十六)——Fisherface人脸识别

文章目录 前言一、Fisherface人脸识别原理1. 核心思想&#xff1a;LDA与Fisher准则2. 实现步骤(1) 数据预处理(2) 计算类内散布矩阵 SW对每个类别&#xff08;每个人&#xff09;计算均值向量 μi&#xff1a;(3) 计算类间散布矩阵 SB(4) 求解投影矩阵 W(5) 降维与分类 3. Fish…...

Unity3D 异步加载材质显示问题排查

前言 在Unity3D中异步加载材质后未正确显示的问题&#xff0c;通常涉及资源加载流程、材质引用或Shader配置。以下是逐步排查和解决问题的方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验呀&#xff01; …...

【Django Serializer】一篇文章详解 Django 序列化器

第一章 Django 序列化器概述 1.1 序列化器的定义 1.1.1 序列化与反序列化的概念 1. 序列化 想象你有一个装满各种物品&#xff08;数据对象&#xff09;的大箱子&#xff08;数据库&#xff09;&#xff0c;但是你要把这些物品通过一个狭窄的管道&#xff08;网络&#xff…...

二分算法的补充说明

在上一节中我们简单介绍了二分算法&#xff0c;通过区分小于等于&#xff0c;大于或者小于&#xff0c;大于等于我们可以求出它们的边界值。 具体方法是先看一下要求哪里的边界值&#xff0c;分成两部分让如果求小于等于的右边界&#xff0c;我们根据条件让rightmid-1,leftmid…...

C++:array容器

array容器是序列容器&#xff0c;它的特点是&#xff1a;静态&#xff0c;固定数目。可以看作更安全的数组。 它还有一些成员函数&#xff0c;如begin&#xff08;&#xff09;&#xff1a;返回指向容器中第一个元素的随机访问迭代器。 #include<iostream>//数组容器 #…...

java每日精进 5.19【Excel 导入导出】

基于 EasyExcel 实现 Excel 的读写操作&#xff0c;可用于实现最常见的 Excel 导入导出等功能。 Excel 导入导出功能涉及前后端协作&#xff0c;后端处理数据查询、文件生成和解析&#xff0c;前端提供用户交互和文件下载/上传界面。以下是全流程解析&#xff0c;分为导出流程…...

java基础(api)

包&#xff1a; 导包&#xff0c;不同包的程序名相同。 但是要用两个的话可以这样子写&#xff1a; String String概述 String的常用方法 String使用时的注意事项 String的应用案例...

CentOS7/Ubuntu SSH配置允许ROOT密码登录

CentOS7 打开SSHD配置文件 vim /etc/ssh/sshd_config 找到注释行&#xff0c;如果没有就添加。 #PermitRootLogin yes 把注释取消掉。 执行下述命令&#xff0c;重启SSHD服务即可。 systemctl restart sshd.service Ubuntu 先安装SSH服务器&#xff0c;CentOS7默认就安…...

C++ HTTP框架推荐

1. Crow 特点&#xff1a;高性能异步框架&#xff0c;支持Linux、macOS和Windows 优势&#xff1a; 轻量级&#xff1a;整个框架只有一个头文件&#xff0c;易于集成到项目中 简单易用&#xff1a;API设计简洁直观&#xff0c;学习曲线平缓 高性能&#xff1a;基于Boost.Asi…...

算法打卡第二天

5.爬楼梯(动态规划) 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶 1 阶 2…...

VSCode推出开源Github Copilot:AI编程新纪元

文章目录 开源决策的背后GitHub Copilot的演进历程Copilot Chat核心功能解析1. 聊天界面集成2. 代码理解与生成3. 多文件编辑能力4. 智能代理模式 开源后的影响与展望对开发者的影响对AI编程工具市场的影响未来发展方向 如何开始使用GitHub Copilot结语相关学习资源 在AI编程助…...

Mujoco 学习系列(四)官方模型仓库 mujoco_menagerie

mujoco 官方在 Github 上发布了一个他们自己整理的高质量的模型仓库&#xff0c;这个仓库是一个持续维护的项目&#xff0c;里面包含了目前市面上常见的人形机器人、机械臂、底盘等模型&#xff0c;对于初学者而言是一个非常好的学习资料&#xff0c;无论是想在仿真环境中尝试还…...

代码走读 Go 语言 Map 的实现

序言 在日常的开发当中&#xff0c;我们一定离不开一个数据结构字典。不仅可以存储关联数据对&#xff0c;还可以在 O(1) 的时间复杂度进行查找。很久之前在 一篇文章带你实现 哈希表 介绍了相关的原理以及简单的实现。所以这篇文章中我们就不多赘述哈希表的原理&#xff0c;而…...

PostgreSQL14 +patroni+etcd+haproxy+keepalived 集群部署指南

使用postgresql etcd patroni haproxy keepalived可以实现PG的高可用集群&#xff0c;其中&#xff0c;以postgresql做数据库&#xff0c;Patroni监控本地的PostgreSQL状态&#xff0c;并将本地PostgreSQL信息/状态写入etcd来存储集群状态&#xff0c;所以&#xff0c;patr…...

数据结构知识点汇总

1、在数据结构中&#xff0c;随机访问是指能够直接访问任一元素&#xff0c;而不需要从特定的起始位置开始&#xff0c;也不需要按顺序访问其他元素。这种访问方式通常不涉及遍历。例如&#xff0c;数组&#xff08;array&#xff09;支持随机访问&#xff0c;你可以直接通过索…...

雅思英语考试基本介绍

考试分类 雅思&#xff08;国际英语语言测试系统&#xff0c;International English Language Testing System 即IELTS&#xff09;主要分为两大类&#xff1a; 学术类&#xff08;A类&#xff09; 这是我可能会选择的一种&#xff08;✓&#xff09;&#xff0c;专为申请大学…...