Java基础--泛型详解
一、背景
java推出泛型之前,集合元素类型可以是object类型,能够存储任意的数据类型对象,但是在使用过程中,如果不知道集合里面的各个元素的类型,在进行类型转换的时候就很容易引发ClassCastException异常。
二、概念
java泛型是jdk5中引入的一种新特新,泛型提供了编译时类型安全监测机制,能够在编译期间检查到非法的类型数据结构。其本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。
三、泛型类、接口
一、泛型类,实例化类的时候指明泛型的具体类型
1、泛型类的定义模版
Class 类名称 <泛型标识,泛型标识,...>{
private 泛型标识 变量名;
.............................
}
2、常用的泛型标识:T、E、K、V
3、使用
类名<具体的数据类型> 对象 = new 类名<具体数据类型,jdk1.7后可以是空的>();
4、注意
1、泛型在创建对象的时候,没有指定类型,将按照Object类型来操作
2、泛型类不支持基本数据类型
3、同一泛型类,根据不同的数据类型创建的对象,本质上是同一个类型。都是这个泛型类的对象,只是里面的泛型做代表的类型不同。
二、从泛型类派生子类
1、子类也是泛型类,子类和父类的泛型类型要一致。
Generic<E> // 这里可以是E,但是下面子类和继承父类的泛型需要一致
class ChildGeneric<T> extends Generic<T>
// 不能子类是T,这里给父类就是E,这表示两个类型是不一致的。原理就是创建子类的时候会先创建父类,如果一致,那么会进行类型传递,告诉父类创建对应类型,如果不一致,将无法得到具体类型。
2、子类不是泛型类,父类要明确泛型的数据类型
class ChildGeneric extends Generic<String>
// 这里需要明确父类数据类型,主要是子类不是泛型类型,无法传递给父类,告知父类泛型该是何种数据类型,所以需要在子类明确
三、泛型接口
1、泛型接口的定义模版
interface 接口名称<泛型标识,泛型标识,........>{
泛型标识 方法名();
..........
}
2、使用
1、实现类不是泛型类,接口需要明确数据类型。原理与不是泛型类的子类实现泛型父类一致。如果不明确,默认就是object类型。
2、实现类是泛型类,实现类与泛型接口的泛型类型要一致。
四、泛型方法
一、语法
修饰符 <T,E,.....> 返回值类型 方法名(参数){
方法体
}
1、修饰符与返回值中间的泛型类型很重要,这个表示声明此方法为泛型方法。
2、 只有在修饰符与返回值中间处声明了<T,E,.....>的方法才是泛型方法,泛型类中使用了泛型的成员方法并不是泛型方法。
3、 <T,E,.....>表示该方法使用泛型,T,E,....,此时才可以在方法中使用对应的泛型类型。
4、如果泛型类上的泛型是T,泛型方法是上面这样声明的,使用的泛型参数也是T,那么在使用时泛型类传入的具体类型,和调用方法时传入的具体类型是没有关系的,相当于这两个T代表的是不同的泛型。也就是说调用时泛型类传入的是Integer,而泛型方法可以传入String,然后用的也是String类型。
5、泛型方法可以使用static,但是泛型类的成员方法,如果使用了泛型类的泛型,则不能使用stiatic,这是因为泛型类型参数是与类的实例相关联的,而不是与类本身相关联的。而
static方法是与类相关联的,它们不依赖于类的实例。
public class MyGenericClass<T> {
private T value;public MyGenericClass(T value) {
this.value = value;
}// 这是一个非静态的泛型方法
public T getValue() {
return value;
}// 这是一个静态方法,但不能使用泛型类型参数T
public static void staticMethod() {
// 在静态方法中不能引用泛型类型参数T
// 下面的代码将会编译错误
// T item = value; // 错误
}
}
在上面的例子中,
getValue方法是一个非静态的泛型方法,因为它依赖于类的实例中的泛型参数。而staticMethod是一个静态方法,它无法直接访问泛型类型参数T,因为它与类的实例无关。在静态方法中,你无法访问类的实例变量,因此也无法访问与实例相关的泛型参数T。
二、泛型方法与可变参数
修饰符 static <E> 返回值类型 方法名(E... e ){
方法体
}
五、类型统配符
一、概述
类型通配符一般是使用“?”代替具体的类型实参,所以通配符是类型实参,而不是类型形参。
二、类型通配符上限
1、语法
类/接口<? extends 实参类型>:要求该泛型的类型,只能是实参类型或者是实参类型的子类类型。
实参形参具体可看:Java方法参数的形参和实参_java 函数 形参-CSDN博客
2、注意
public void test(ArrayList<? extends cat> list){
1、 这里需要注意 list在方法体内是无法添加元素的,这是由于传入的不知道是cat还是cat的子类,那添加元素就无法确定添加那种数据,假如说传入的是cat的子类A,这个时候我们并不知道,就有可能添加cat的子类B。
2、这里可以使用cat来接受元素类型
}
三、类型通配符的下限
1、语法
类/接口<? super 实参类型>:要求该泛型的类型,只能是实参类型或者是实参类型的父类类型。
2、 注意
public void test(ArrayList<? super cat> list){
1、这里需要注意 list可以在方法体内添加元素,通配符下限并不约束元素类型。
2、遍历时使用的是Object来接收元素
}
六、类型擦除
一、无限制擦除
一般是使用除extends的上限通配符,其他的泛型类型都会在编译期间进行类型擦除,将泛型转为Object类型。
二、有限制擦除
使用了泛型的上限通配符时,在编译期间进行类型擦除,将泛型转为上限类型。
三、桥接方法

七、泛型数组
一、可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象。例如:
ArrayList<String>[] list = new ArrayList<String>[]; // 这样是会编译报错的
ArrayList<String>[] list = new ArrayList[]; // 只能这样,创建一个非泛型数组对象,再赋值给list变量。
出现这个现象的原因就是:泛型会在编译期间进行类型擦,而数组刚好相反,在编译期间也会一直持有对应的类型,所以这两种一开始就是对立的。
二、可以通过java.lang.reflect.Array的newInstance(Class<T> class,int length)方法创建泛型数组。
八、泛型和反射
常用:Class<T>和Constructor<T>
相关文章:
Java基础--泛型详解
一、背景 java推出泛型之前,集合元素类型可以是object类型,能够存储任意的数据类型对象,但是在使用过程中,如果不知道集合里面的各个元素的类型,在进行类型转换的时候就很容易引发ClassCastException异常。 二、概念 …...
学习搜狗的workflow,MacBook上如何编译
官网说可以在MacBook上也可以运行,但是编译的时候却有找不到openssl的错误: 看其他博客也有类似的错误,按照类似的思路去解决 问题原因和解决办法 cmake编译的时候,没有找到openssl的头文件,需要设置cmake编译环境下…...
Ubuntu使用cmake和vscode开发自己的项目,引用自己的头文件和openCV
创建文件夹 mkdir my_proj 继续创建include 和 src文件夹,形成如下的目录结构 用vscode打开项目 创建add.h #ifndef ADD_H #define ADD_Hint add(int numA, int numB);#endif add.cpp #include "add.h"int add(int numA, int numB) {return numA nu…...
2) dataset, dataloader
dataset, dataloader torchvision.datasets里面集成了一些常见的数据集,例如MNIST和CIFAR10 1) Dataset 以MNIST为例,其使用方式如下 import torch import torchvision from torchvision import transformstrain_dataset = torchvision.datasets.MNIST(root=../data,trai…...
阿里云PolarDB自研数据库详细介绍_兼容MySQL、PostgreSQL和Oracle语法
阿里云PolarDB数据库是阿里巴巴自研的关系型分布式云原生数据库,PolarDB兼容三种数据库引擎:MySQL、PostgreSQL、Oracle(语法兼容),目前提供云原生数据库PolarDB MySQL版、云原生数据库PolarDB PostgreSQL版和云原生数…...
[软件工具]opencv-svm快速训练助手教程解决opencv C++ SVM模型训练与分类实现任务支持C# python调用
opencv中已经提供了svm算法可以对图像实现多分类,使用svm算法对图像分类的任务多用于场景简单且对时间有要求的场景,因为opencv的svm训练一般只需要很短时间就可以完成训练任务。但是目前网上没有一个工具很好解决训练问题,大部分需要自己编程…...
邮件注册(一)验证码发送
通过邮箱实现注册,用户请求验证码完成注册操作。 导入依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><g…...
【网络安全---sql注入(2)】如何通过SQL注入getshell?如何通过SQL注入读取文件或者数据库数据?一篇文章告诉你过程和原理。
前言 本篇博客主要是通过piakchu靶场来讲解如何通过SQL注入漏洞来写入文件,读取文件。通过SQL输入来注入木马来getshell等,讲解了比较详细的过程; 如果想要学习SQL注入原理以及如何进行SQL注入,我也写了一篇详细的SQL注入方法及…...
正点原子嵌入式linux驱动开发——TF-A移植
经过了之前的学习,除了TF-A的详细启动流程仍待更新,TF-A的使用和其对应的大致启动流程已经进行过了学习。但是当我们实际做产品时,硬件平台肯定会和ST官方的有区别,比如DDR容量会改变,自己的硬件没有使用到官方EVK开发…...
GB28181学习(六)——实时视音频点播(数据传输部分)
GB28181系列文章: 总述:https://blog.csdn.net/www_dong/article/details/132515446 注册与注销:https://blog.csdn.net/www_dong/article/details/132654525 心跳保活:https://blog.csdn.net/www_dong/article/details/132796…...
JMeter接口自动化测试(数据驱动)
之前我们的用例数据都是配置在HTTP请求中,每次需要增加,修改用例都需要打开JMeter重新编辑,当用例越来越多的时候,用例维护起来就越来越麻烦,有没有好的方法来解决这种情况呢?我们可以将用例的数据存放在cs…...
数据结构:二叉树(超详解析)
目录 1.树概念及结构 1.1树的概念 1.2树的相关概念 1.3树的表示 1.3.1孩子兄弟表示法: 1.3.2双亲表示法:只存储双亲的下标或指针 两节点不在同一树上: 2.二叉树概念及结构 2.1.概念 2.2.特殊的二叉树: 2…...
【考研数学】高等数学第七模块 —— 曲线积分与曲面积分 | 4. 对坐标的曲面积分(第二类曲面积分)与场论初步
文章目录 二、曲面积分2.2 对坐标的曲面积分(第二类曲面积分)1. 问题产生 —— 流量2. 对坐标的曲面积分的定义(了解)3. 对坐标的曲面积分的性质4. 对坐标的曲面积分的计算法(1) 二重积分法(2&a…...
使用Thrift实现跨语言RPC调用
📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜📝 个人主页:馆主阿牛🔥🎉 支持我:点赞👍收藏⭐️留言Ὅ…...
【QT5-程序控制电源-RS232-SCPI协议-上位机-基础样例【1】】
【QT5-程序控制电源-RS232-SCPI协议-上位机-基础样例【1】】 1、前言2、实验环境3、自我总结1、基础了解仪器控制-熟悉仪器2、连接SCPI协议3、选择控制方式-程控方式-RS2324、代码编写 4、熟悉协议-SCPI协议5、测试实验-测试指令(1)硬件连接(…...
leetcode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零
1049. 最后一块石头的重量 II 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x < y。那么粉碎的可能结果…...
Error string: Could not load library
启动Rivz时,报错: Error string: Could not load library (Poco exception libg2o_csparse_extension.so.0.1: cannot open shared object file: No such file or directory) [ERROR] [1696572310.529059051]: Failed to load nodelet [/radar_graph_s…...
pom.xml里的标签
pom.xml 是 Maven 项目的配置文件,其中包含了各种配置信息和依赖管理。下面是一些常见的 pom.xml 中的标签和其作用的简要说明: <project>:根标签,定义了整个项目的基本信息和结构。 <groupId>:指定项目所…...
微服务部署的正确策略
微服务部署挑战 单体应用程序的部署意味着您运行单个(通常是大型应用程序)的多个相同副本。这主要是通过配置 N 个服务器(无论是物理服务器还是虚拟服务器)并在每台服务器上运行应用程序的 M 个实例来完成。虽然这看起来非常简单…...
C#中的数组探究与学习
目录 C#中的数组一般分为:一.数组定义:为什么要使用数组?什么是数组?C#一维数组for和foreach的区别C#多维数组C#锯齿数组初始化的意义:适用场景:C#中的数组一般分为: ①.一维数组。 ②.多维数组,也叫矩形数组。 ③.锯齿数组,也叫交错数组。 一.数组定义: 数组…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
