java加强 -泛型
概念
定义类、接口、方法时,同时声明了一个或多个类型变量(如<E>),称为泛型类、泛型接口、泛型方法、它们统称为泛型。
语法
public class ArrayList<E>{}
E可以接收不同类型的数据,可以是字符串,也可以是学生类等东西。
作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力,这样可以避免强制类型转换,及其可能出现的异常。
接下来用常见API,ArrayList集合举例
package GenericityDemo;import java.util.ArrayList;public class GenericDemo1 {public static void main(String[] args) {
// //认识泛型
// ArrayList list = new ArrayList(); //没有使用泛型,存储任意类型数据
// list.add("hello");
// list.add(100);
// list.add(true);
// //获取数据
// for (int i = 0; i < list.size(); i++)
// {
// Object obj = list.get(i); //必须用Object接收,因为存储的任意类型数据
// //数据转型处理
// String s = (String) list.get(i);//运行到整型时程序会崩,因此最好要统一数据类型
// System.out.println(s);
// }ArrayList<String> list = new ArrayList<String>(); //泛型约束,只能存储String类型数据list.add("hello");list.add("world");//list.add(90); //类型不是泛型约束的类型,报错for (int i = 0; i < list.size(); i++){String s = list.get(i); //类型确定,不用转型System.out.println(s); //不会出现异常}}
}
一、泛型类
泛型类(Generic Class) 是通过类型参数化定义的类,其核心作用是通过类型抽象实现代码的通用性、类型安全性和灵活性。
语法
修饰符 class 类名<类型变量,类型变量....>{}
public class ArrayList<E>{
......
}
示例
创建一个ArrayList集合类(其实就是在自己的类里用之前的API,但接收的数据类型由我们限制)
package GenericityDemo;import java.util.ArrayList;public class MyArrayList <E>{private ArrayList list = new ArrayList();public boolean add(E e){list.add(e);return true;}public boolean remove(E e){return list.remove(e);}@Overridepublic String toString() {return list.toString();}
}
package GenericityDemo;public class GenericDemo2 {public static void main(String[] args) {//目标:学会自定义泛型类//需求:模拟ArrayList集合,自定义一个集合MyArrayListMyArrayList<String> list = new MyArrayList<>();//jdk7支持后面不写泛型类型list.add("java");list.add("后端");System.out.println(list);}
}
类型变量建议使用大写的英文字母,常用的有:E、T、K、V等
E:常用于集合类(如 List
、Set
),强调泛型参数是容器内的元素。
T:当泛型类或方法不限制具体类型时,常用 T
作为默认类型占位符。
K/V:用于键值对数据结构(如 Map
)中,明确区分键和值的类型。
二、泛型接口
泛型接口(Generic Interface) 是通过类型参数化定义的接口,其核心作用是通过类型抽象提高代码的复用性、类型安全性和灵活性。
修饰符 interface 接口名<类型变量,类型变量...>{
}
public interface A<E>{
...
}
示例
对学生数据/老师数据都要进行增删查改操作。
定义一个泛型接口可以接学生或老师对象进行操作,可以实现一个方法操作两个角色。
package GenericityDemo3;public interface Data<T> {
// void add(Student s);
// void add(Teacher t);//类型约定死了,,只能存Student或Teacher//利用泛型接口void add(T t); //此时泛型可以为Teacher也能为Studentvoid delete(T t);void update(T t);T query(int id);
}
(此示例并没有真正实现增删查改操作,只为示范)
package GenericityDemo3;public class Student {
}
package GenericityDemo3;public class Teacher {
}
创造两个类用于实现Data,一个实现老师操作,一个实现学生操作
package GenericityDemo3;public class TeacherData implements Data<Teacher>{//操作老师数据@Overridepublic void add(Teacher teacher) {}@Overridepublic void delete(Teacher teacher) {}@Overridepublic void update(Teacher teacher) {}@Overridepublic Teacher query(int id) {return null;}
}
package GenericityDemo3;public class StudentData implements Data<Student>{//专门操作学生对象@Overridepublic void add(Student student) {}@Overridepublic void delete(Student student) {}@Overridepublic void update(Student student) {}@Overridepublic Student query(int id) {return null;}
}
package GenericityDemo3;public class GenericDemo3 {public static void main(String[] args) {//目标:搞清楚泛型接口的基本应用//需求:项目需要对学生数据/老师数据都要进行增删查改操作StudentData studentData = new StudentData();studentData.add(new Student()); //添加学生数据.对学生操作Student s = studentData.query(1001);}
}
通过泛型接口,可以为不同类型的数据定义统一的处理逻辑,同时避免强制类型转换和运行时类型错误。
三、泛型方法
泛型方法(Generic Method) 是通过在方法签名中声明类型参数来实现的方法级别泛型化。它与泛型类的主要区别在于作用范围:泛型方法的类型参数仅作用于该方法内部,而非整个类。
语法
修饰符<类型变量,类型变量,...>返回值类型 方法名(形参列表){}
示例
现在我需要一个方法将数组的内容打印出来
package GenericDemo4;public class GenericDemo4 {//目标:理解泛型方法public static void main(String[] args) {//需求:打印任意数组的内容String[] arr1 = {"hello","world","java"};printArray(arr1);Student[] arr2 = new Student[3];//printArray(arr2);//只能接收String类型数组Student s1 = getMax(arr2); printArray2(arr1);getMax(arr2); //泛型方法,可以接收任意类型的数组,避免强转}public static void printArray(String[] arr){for (int i = 0; i < arr.length; i++) {System.out.println(arr[i] + " ");}}public static <T> void printArray2(T[] arr){for (int i = 0; i < arr.length; i++) {System.out.println(arr[i] + " ");}}public static <T> T getMax(T[] name){return null;}
}
上述代码有两个方法,一个是printArray一个是printArray2,但printArray有一个缺点就是只能打印字符串数组的内容,若是其他数组则无法接收。因此,我们可以做一个泛型方法即printArray2,它可以接收String数组也可以接收Student数组,实现了一个方法解决多个问题。
四、通配符与上下限
当我们要传的参数为多个集合,每个集合都是继承于某个父类的子类的集合时,我们就可以通过使用通配符来接收不同的子类集合。(注:例如两个集合为ArrayList<Cat>和ArrayList<Dog>,不能用ArrayList<Animal>接收,因为他们本质上是不同的集合,虽然他们的子类继承了同一个父类)
示例
package GenericDemo4;public class Car {
}
package GenericDemo4;public class BYD extends Car{}
package GenericDemo4;public class BMW extends Car{
}
package GenericDemo4;import java.util.ArrayList;public class GenericDemo5 {public static void main(String[] args) {//目标:理解通配符和上下限ArrayList<BYD> byds = new ArrayList<>();byds.add(new BYD());byds.add(new BYD());byds.add(new BYD());//go(byds); //报错不具备通用性ArrayList<BMW> bmws = new ArrayList<>();bmws.add(new BMW());bmws.add(new BMW());bmws.add(new BMW());go(bmws);}//模拟极品飞车游戏//虽然比亚迪和宝马是Car的子类,但ArrayList<BYD>和ArrayList<BMW>和ArrayList<Car>是不同的,因此不能用多态
// public static void go(ArrayList<BMW> cars)
// {
//
// }//通配符,在使用泛型时代表一切类型public static void go(ArrayList<?> cars){}
}
然而,若是这么写这个方法能接收的集合范围又太大了,连猫和狗都可以进这个开汽车的方法,因此需要使用上下限来加以限制。
? extends Car ?能接收Car或者Car的子类(泛型上限)
? super Car ?能接收Car或者Car的父类(泛型下限)
package GenericDemo4;import java.util.ArrayList;public class GenericDemo5 {public static void main(String[] args) {//目标:理解通配符和上下限ArrayList<BYD> byds = new ArrayList<>();byds.add(new BYD());byds.add(new BYD());byds.add(new BYD());//go(byds); //报错不具备通用性ArrayList<BMW> bmws = new ArrayList<>();bmws.add(new BMW());bmws.add(new BMW());bmws.add(new BMW());go(bmws);}//模拟极品飞车游戏//虽然比亚迪和宝马是Car的子类,但ArrayList<BYD>和ArrayList<BMW>和ArrayList<Car>是不同的,因此不能用多态
// public static void go(ArrayList<BMW> cars)
// {
//
// }//通配符,在使用泛型时代表一切类型//为了防止将狗,猫等不属于车的类型传入方法,使用泛型的上下限限制//? extends Car ?能接收Car或者Car的子类(泛型上限)//? super Car ?能接收Car或者Car的父类(泛型下限)public static void go(ArrayList<? extends Car> cars){}
}
这样,就能将这个方法限制在接收汽车类的子类了。
五、泛型支持的数据类型
泛型不支持基本的数据类型,即int,double等数据类型,原因是泛型工作在编译阶段,编译结束后系统会进行泛型擦除,所有类型都会转变为Object类型。而Object是对象类型,接收的是对象,数字等类型不是对象,因此不接收基本的数据类型。为了能够兼容基本的数据类型,java的库里添加了包装类,用于将基本数据类型变为对象。
包装类有8种。
int -> Integer char -> Character ,其它的都是首字母大小写。
package GenericDemo5;import java.util.ArrayList;
import java.util.Objects;public class GenericDemo5 {public static void main(String[] args) {//目标:搞清楚泛型和集合不支持基本数据类型,只能支持对象类型(引用类型)//ArrayList<double> list = new ArrayList<>(); //报错,不支持//泛型擦除:泛型工作在编译阶段,等编译后泛型就没用了,所以泛型在编译后都会被擦除。所有类型会恢复为Object类型。//Object是对象类型,不能直接指向某个数,只能指向某个对象。//因此要使用包装类,比如Integer、Double、Character、Boolean等。//包装类的作用:把基本数据类型包装成对象类型。//ArrayList<int> list = new ArrayList<>();//list.add(12); //12不是对象,报错ArrayList<Integer> list = new ArrayList<>();list.add(12); //自动装箱,把基本数据类型12包装成Integer对象。int rs= list.get(0); //自动拆箱,把Integer对象12拆箱成基本数据类型。//把基本数据类型变成包装类对象//手工包装//Integer i = new Integer(12);//从jdk9开始,这个方法被淘汰了(过时)//推荐用valueOf的原因:valueOf方法中缓存了-128~127的数值,重复创建这个范围内的数字时不会创建新对象,而是直接返回缓存中的对象。//缓存对象范围是-128~127,如果超过这个范围,就会创建新的对象。//更优雅,节约内存。Integer i = Integer.valueOf(12); //此时i为对象,里面存储的是12Integer i2 = Integer.valueOf(12);System.out.println(i == i2); //ture, 因为i和i2是同一个对象//自动装箱Integer i3 = 12; //与Integer i = Integer.valueOf(12)一个意思Integer i4 = 12;System.out.println(i3 == i4);//自动拆箱:把包装类型的对象直接给基本类型的数据int i5 = i3;System.out.println(i5);System.out.println("========================================================");//包装类新增的功能//1、把基本类型的数据变成字符串int j=23;String rs1 = Integer.toString(j);System.out.println(rs1+1); //不是24,说明已经是字符串Integer i6=j;String rs2 = i6.toString();System.out.println(rs2+1);String rs3 = i6+""; //直接加""转换为字符串System.out.println(rs3+1);System.out.println("========================================================");//把字符串数值转换成对应的基本数据类型String str = "123";int i1 = Integer.parseInt(str);int i9 = Integer.valueOf(str);System.out.println(i1+1);System.out.println(i9+1);}
}
相关文章:
java加强 -泛型
概念 定义类、接口、方法时,同时声明了一个或多个类型变量(如<E>),称为泛型类、泛型接口、泛型方法、它们统称为泛型。 语法 public class ArrayList<E>{} E可以接收不同类型的数据,可以是字符串&…...
pygame联网飞机大战游戏实现
客户端 import pygame import socket import json import threadingclass GameClient:def __init__(self):pygame.init()self.screen_width 600 # 宽度减小self.screen_height 800 # 高度增加self.screen pygame.display.set_mode((self.screen_width, self.screen_heigh…...

SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理标准)-(二)
8 行为规范 8.1 本章定义监督实体(Supervisor)与加工资源(Processing Resource)为实现物料加工所需的高层级通信逻辑,不涉及具体消息细节(详见第10章消息服务)。 8.2 加工任务通信 8.2.1 加工…...

根据窗口大小自动调整页面缩放比例,并保持居中显示
vue 项目 直接上代码 图片u1.png 是个背景图片 图片u2.png 是个遮罩 <template><div id"app"><div class"viewBox"><divclass"screen":style"{ transform: translate(-50%,-50%…...
如何在Jmeter中调用C程序?
在JMeter中调用C语言程序可以通过以下几种方式实现: 方法一:使用OS Process Sampler JMeter的“OS Process Sampler”可以用来调用外部程序,包括C语言编写的可执行文件。 步骤: 准备C语言程序: 编写C语言代码并编译…...

Android SDK 国内镜像及配置方法(2025最新,包好使!)
2025最新android sdk下载配置 1、首先你需要有android sdk manager2、 直接上教程修改hosts文件配置域名映射即可(不用FQ)2.1 获取ping dl.google.com域名ip地址2.2 配置hosts文件域名映射2.3 可以随意下载你需要的sdk3、 总结:走过弯路,踩过坑!!!大家就不要踩了!避坑1…...

【Python开源】深度解析:一款高效音频封面批量删除工具的设计与实现
🎵 【Python开源】深度解析:一款高效音频封面批量删除工具的设计与实现 🌈 个人主页:创客白泽 - CSDN博客 🔥 系列专栏:🐍《Python开源项目实战》 💡 热爱不止于代码,热情…...

OpenStack Yoga版安装笔记(26)实例元数据笔记
一、实例元数据概述 1.1 元数据 (官方文档:Metadata — nova 25.2.2.dev5 documentation) Nova 通过一种叫做元数据(metadata)的机制向其启动的实例提供配置信息。这些机制通常通过诸如 cloud-init 这样的初始化软件…...

【Linux】swap交换分区管理
目录 一、Swap 交换分区的功能 二、swap 交换分区的典型大小的设置 2.1 查看交换分区的大小 2.1.1 free 2.1.2 cat /proc/swaps 或 swapon -s 2.1.3 top 三、使用交换分区的整体流程 3.1 案例一 3.2 案例二 一、Swap 交换分区的功能 计算机运行一个程序首先会将外存&am…...
Spring IoC (Inversion of Control) 控制反转是什么?
我们分析一下 IoC (Inversion of Control) 控制反转的核心思想。 核心思想: IoC 是一种设计原则(Design Principle),它描述了一种软件设计模式,其中组件(对象)的创建、依赖关系的管理和生命周…...
互联网大厂Java求职面试:核心技术点深度解析
互联网大厂Java求职面试:核心技术点深度解析 在互联网大厂的Java岗位面试中,技术总监级别的面试官通常会从实际业务场景出发,层层深入地考察候选人的技术能力。本文通过一个严肃专业的技术总监与搞笑但有技术潜力的程序员郑薪苦之间的互动对…...

VirtualBox 创建虚拟机并安装 Ubuntu 系统详细指南
VirtualBox 创建虚拟机并安装 Ubuntu 系统详细指南 一、准备工作1. 下载 Ubuntu 镜像2. 安装 VirtualBox二、创建虚拟机1. 新建虚拟机2. 分配内存3. 创建虚拟硬盘三、配置虚拟机1. 加载 Ubuntu 镜像2. 调整处理器核心数(可选)3. 启用 3D 加速(图形优化)四、安装 Ubuntu 系统…...
【算法基础】递归算法 - JAVA
一、递归基础 1.1 什么是递归算法 递归算法是一种通过函数调用自身来解决问题的方法。简单来说,就是"自己调用自己"。递归将复杂问题分解为同类的更简单子问题,直到达到易于直接解决的基本情况。 1.2 递归的核心要素 递归算法由两个关键部…...

触想CX-3588工控主板应用于移动AI数字人,赋能新型智能交互
一、行业发展背景 随着AI智能、自主导航和透明屏显示等技术的不断进步,以及用户对“拟人化”、“沉浸式”交互体验的期待,一种新型交互终端——“移动AI数字人”正在加速实现规模化商用。 各大展厅展馆、零售导购、教学政务甚至家庭场景中,移…...

【深入浅出MySQL】之数据类型介绍
【深入浅出MySQL】之数据类型介绍 MySQL中常见的数据类型一览为什么需要如此多的数据类型数值类型BIT(M)类型INT类型TINYINT类型BIGINT类型浮点数类型float类型DECIMAL(M,D)类型区别总结 字符串类型CHAR类型VARCHAR(M)类型 日期和时间类型enum和set类型 …...

Vue3响应式:effect作用域
# Vue3响应式: effect作用域 什么是Vue3响应式? 是一款流行的JavaScript框架,它提供了响应式和组件化的视图组织方式。在Vue3中,响应式是一种让数据变化自动反映在视图上的机制。当数据发生变化时,与之相关的视图会自动更新。 作用…...

25.5.4数据结构|哈夫曼树 学习笔记
知识点前言 一、搞清楚概念 ●权:___________ ●带权路径长度:__________ WPL所有的叶子结点的权值*路径长度之和 ●前缀编码:____________ 二、构造哈夫曼树 n个带权值的结点,构造哈夫曼树算法: 1、转化成n棵树组成的…...

RabbitMQ 深度解析:从核心组件到复杂应用场景
一.RabbitMQ简单介绍 消息队列作为分布式系统中不可或缺的组件,承担着解耦系统组件、保障数据可靠传输、提高系统吞吐量等重要职责。在众多消息队列产品中,RabbitMQ 凭借其可靠性和丰富的特性,在企业级应用中获得了广泛应用。 二.RabbitMQ …...
Python高级技巧及案例分析:提升编程能力的实践指南
目录 Python高级技巧及案例分析:提升编程能力的实践指南1. Python高级特性概述2. 函数式编程技巧2.1 高阶函数2.2 函数柯里化2.3 不可变数据结构3. 元编程与反射3.1 动态属性访问3.2 类装饰器3.3 元类应用4. 并发与异步编程4.1 多线程与线程池4.2 协程与asyncio4.3 多进程处理…...

【Linux笔记】系统的延迟任务、定时任务极其相关命令(at、crontab极其黑白名单等)
一、延时任务 1、概念 延时任务(Delayed Jobs)通常指在指定时间或特定条件满足后执行的任务。常见的实现方式包括 at 和 batch 命令,以及结合 cron 的调度功能。 2、命令 延时任务的命令最常用的是at命令,第二大节会详细介绍。…...
转换算子和行动算子的区别
转换算子和行动算子主要是在分布式计算框架(如 Apache Spark)里常用的概念,它们在功能、执行机制、返回结果等方面存在明显区别,以下为你详细介绍: 定义与功能 返回结果 如何在使用转换算子和行动算子时避免出现内存溢…...

使用阿里AI的API接口实现图片内容提取功能
参考链接地址:如何使用Qwen-VL模型_大模型服务平台百炼(Model Studio)-阿里云帮助中心 在windows下,使用python语言测试,版本:Python 3.8.9 一. 使用QVQ模型解决图片数学难题 import os import base64 import requests# base 64 …...
告别散乱的 @ExceptionHandler:实现统一、可维护的 Spring Boot 错误处理
Spring Boot 的异常处理机制一直都烂得可以。即便到了 2025 年,有了这么多进步和新版本,开发者们发现自己还是在跟 ControllerAdvice、分散各处的 ExceptionHandler 方法以及五花八门的响应结构较劲。这真的是一团糟。 无论你是在构建 REST API、微服务…...
MariaDB 与 MySQL 的关系:从同源到分道扬镳
MariaDB 与 MySQL 的关系:从同源到分道扬镳 1. 起源:MySQL 的辉煌与危机 MySQL 是最流行的开源关系型数据库之一,由瑞典公司 MySQL AB 开发,并于 1995 年 首次发布。由于其高性能、易用性和开源特性,MySQL 迅速成为 L…...

从零开始搭建你的个人博客:使用 GitHub Pages 免费部署静态网站
🌐 从零开始搭建你的个人博客:使用 GitHub Pages 免费部署静态网站 在互联网时代,拥有一个属于自己的网站不仅是一种展示方式,更是一种技术能力的体现。今天我们将一步步学习如何通过 GitHub Pages 搭建一个免费的个人博客或简历…...

C#串口通信
在C#中使用串口通信比较方便,.Net 提供了现成的类, SerialPort类。 本文不对原理啥的进行介绍,只介绍SerialPort类的使用。 SerialProt类内部是调用了CreateFile,WriteFile等WinAPI函数来实现串口通信。 在后期的Windows编程系…...
Qt 显示QRegExp 和 QtXml 不存在问题
QRegExp 和 QtXml 问题 在Qt6 中 已被弃用; 1)QRegExp 已被弃用,改用 QRegularExpression Qt5 → Qt6 重大变更:QRegExp 被移到了 Qt5Compat 模块,默认不在 Qt6 核心模块中。 错误类型解决方法QRegExp 找不到改用 Q…...
【训练】Qwen2.5VL 多机多卡 Grounding Box定位
之前的相关文章: 【深度学习】LLaMA-Factory微调sft Qwen2-VL进行印章识别 https://www.dong-blog.fun/post/1661 使用LLaMA-Factory微调sft Qwen2-VL-7B-Instruct https://www.dong-blog.fun/post/1762 构建最新的LLaMA-Factory镜像 https://www.dong-blog.f…...

服务器配置llama-factory问题解决
在配置运行llama-factory,环境问题后显示环境问题。这边给大家附上连接,我们的是liunx环境但是还是一样的。大家也记得先配置虚拟环境。 LLaMA-Factory部署以及微调大模型_llamafactory微调大模型-CSDN博客 之后大家看看遇到的问题是不是我这样。 AI搜索…...

Spring Boot + Vue 实现在线视频教育平台
一、项目技术选型 前端技术: HTML CSS JavaScript Vue.js 前端框架 后端技术: Spring Boot 轻量级后端框架 MyBatis 持久层框架 数据库: MySQL 5.x / 8.0 开发环境: IDE:Eclipse / IntelliJ IDEA JDK&…...