Java泛型--Java中的E、T、?

news2024/11/16 11:43:52

🍁 先说结论:

  • T、E、K、V、?本质都是通配符。用于定义泛型类、泛型方法、泛型接口…换成其他字母也行,只是这几个字母是一种编码约定。
  • T,即type,表示一个具体的Java类型
  • E,即element,常用于集合,如List<E>、Set<E>
  • K V 即key . value,常用于Map的键值对
  • ? 表示不确定的Java类型(详细看后面)


1、初识泛型

Object类型可以接收任意类型,但实际应用中会有类型转换的问题。先看一下没有泛型时,写代码:

List myList = new ArrayList();
myList.add(new Integer(23));

我看到集合中放进去了一个Integer类型的数据,但我get(index)拿到的是Object类型,必须向下转型为Integer。

Integer i = (Integer) myList.get(0);

引入泛型,即为集合中的元素指定一个统一的类型

List<Intger> myList = new ArrayList<>();
myList.add(new Integer(23));
//此时,不再需要转型
Integer i = myList.get(0);

泛型总结即:

  • 在JDK5.0之后的新特性–泛型
  • 泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的,运行阶段泛型没用
  • 写了泛型而不用,那就是Object类型
  • 泛型的优点是:集合中存储的元素类型统一,从集合中取出的元素类型是泛型指定的类型,不需要进行大量的向下转型
  • 泛型的缺点是:导致集合中存储的元素缺乏多样性,但日常开发中类型统一,所以泛型应用较多

泛型在日常开发中大量用在集合当中,即统一元素类型,避大量向下转型,也就是上面总结的。除了这一点,泛型的使用方式还有:

  • 泛型类
  • 泛型方法
  • 泛型接口

这时,泛型的作用是:把明确类型的工作推迟到创建对象或者调用方法时才明确

2、泛型类

定义泛型类,语法:

修饰符 class 类名<泛型通配符>{

}

例1:

//类中有属性类型为T
//这里的<T>中的T是标识符,随便写,但<T>常用些

@Getter
@Setter
public class MyClass<T> {

	private Integer id;

	private T data;

	private T info;

}

此时,使用泛型类:

MyClass<String> myClass = new MyClass<>();
myClass.setData("code-9527");

例2:

//类中有方法的形参类型为T

public class GenericTest<T>{
	
    public void doSome(T x){
        System.out.println(x);
    }

    public static void main(String[] args) {
        GenericTest<String> g1 = new GenericTest<>();
        g1.doSome("code");
        
        GenericTest<Integer> g2 = new GenericTest<>();
        g2.doSome(9527);
        
        //写了泛型而不用,那就是Object类型
        GenericTest g3 = new GenericTest();
        //这里传参是Object类型
        g3.doSome();
    }
}

当然,也可以指定多泛型

public class MoreGeneric<T,N,A,B>{

	private T data;
	
	private N num;

	private A arg;

	public static void doSome(T t){
		//doSome
	}
}

3、泛型方法

泛型方法,即调用时才指明泛型的具体类型。语法格式:

修饰符 <泛型通配符变量> 返回值类型 方法名(形参){

}
  • public和返回值类型之间的<T>是声明此方法为泛型方法
  • <T>表明在方法可以使用声明的泛型类型,即T类型
  • 泛型方法可以声明为 static 的

例1:

public <T> void doSome(T t){

	System.out.println("doSome...");
	
}

例2:

public class GenericDemo{
	public <T> T genericMethod(T t){
		System.out.println(t.getClass());
		System.out.println(t);
		return t;
	}

}

调用泛型方法:

在这里插入图片描述

例3:泛型方法中的变长参数

public class GenericDemo{

	public <A> A[] argsMethod(A ... args){
		for(A arg : args){
			System.out.println(arg);
		}
		return args; //返回泛型数组
	}
}

//调用 new GenericDemo().argsMethod('a','b','c','d','e');

在这里插入图片描述

例4:静态泛型方法

public static <T,E> String staticGeneric(String str,T t,E e){
	String res = "";
	res += str + "--" + t + "--" + e'
	return res;

}

//调用还是直接类名.方法名

4、泛型接口

和定义泛型类相似,语法:

修饰符 interface 接口名<泛型统配>
public interface GenericInterface<T>{

	T updateSome(Integer id);

	public abstract void addSome(T t);
}

此时写接口的实现类,可以:

  • 在定义实现类时确定泛型的类型
public class GenericsImpl implements GenericsInterface<String> {

 @Override
 public void addSome(String s) {
 System.out.println("定义实现类时确定泛型的类型");
    }
}
  • 始终不确定泛型的类型,交给创建对象时确定
public class GenericsImpl<T> implements GenericsInterface<T> {

 @Override
 public void addSome(T t) {
 System.out.println("不确定泛型类型,交给创建对象时确定");
    }
}


//在测试程序中
public class Test{
	public static void main(String[] args){
		GenericsImpl<Integer> obj = new GenericsImpl<>();
		obj.addSome(9527);
	}
}

5、未知通配符?

  • ? - 表示不确定的java类型,常用于形参中
  • T是一个确定的类型,常用于泛型类和泛型方法。
public class TestClass<T>{
	
	private T t;
	
	public void test(List<?> list){
	
	}
}
  • ?和 T,声明了T类型以后,T可以操作,而?不行
    在这里插入图片描述

  • T只能用extends来限定缩小范围,而?可以使用extends和super
    在这里插入图片描述

6、未知通配符的高级使用

//测试数据:

class Animal{}//父类class Dog extends Animal{}//子类class Cat extends Animal{}//子类

泛型的上限:

  • 格式:<? extends 类A>
  • 意义: 实例化时的类只能是类型A及其子类型
    在这里插入图片描述
  • 举例:
//接口中定义的抽象方法
List<? extends Animal> listSome();

//实现类中重写
@Override
public List<Animal> listSome(){

	return null;
}
//再比如某方法的形参中:

public void doSome(List<? extends Animal> list){

}
//此时实例化时:

list = new ArrayList<Animal>();  //√
list = new ArrayList<Dog>();  //√
list = new ArrayList<Object>();  //×
  • 注意点1: 上界通配符下add失效(只能add null),可以get
List<? extends Animal> list;
list = new ArrayList<Animal>(); 
list.add(new Animal());  //编译error
list.add(null);  //√
list.get(0); //√
  • 注意点2: 既然不能add,那么想加元素就得在实例化时就放进去
List<? extends Animal> list;
list = new ArrayList<Animal>(){
	{
		add(new Animal());
		add(new Dog());
	}
}; 
  • 注意点3: 能add的元素的类型是实例化时指定的类型及其子类
List<? extends Animal> list;
list = new ArrayList<Dog>(){
	{
		add(new Animal()); //指定Dog后,编译error
		add(new Dog()); //可以add的是Dog及其子类
	}
}; 

泛型的下限:

  • 格式:<?super 类A>

  • 意义: 实例化时的类只能是类型A及其父类型
    在这里插入图片描述

  • 举例:

List<? super Animal> list ;
list = new ArrayList<Object>();  //√
list = new ArrayList<Animal>();  //√
list = new ArrayList<Dog>();  //×
  • 注意点1: 添加对象时,在实例化时添加和实例化后添加,限制不同。
class SomeOne {}

class People extends SomeOne{}

class Animal extends SomeOne{}

实例化时添加对象,可以添加A类的父类的其他子类:


List<? super Animal> list = new ArrayList<SomeOne>(){
	{
		add(new Object()); //error,超过了Someone
		add(new People()); //√ 是SomeOne的子类,但和Animal无关
		add(new SomeOne());  //√
		add(new Animal()); //√
		add(new Dog());  //√
	}

}

实例化后,恢复成只能add类A和其子类

list.add(new SomeOne()); //error
list.add(new People());  //error
add(new Animal()); //√
add(new Dog());  //√
  • 注意点2: 上界通配符get出来的对象默认是Object类型,可根据需要强转
Object obj = list.get(0);
Animal a = (Animal)list.get(0);

后面有内容再补吧,?这个是真有毒。

add元素限制的问题,参考:【Java擦除】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/439008.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023测试人必备60个实用测试工具推荐,让你成为测试大咖

目录 引言 一、测试管理工具 二、接口测试工具 三、性能测试工具 四、C/S自动化工具 五、白盒测试工具 六、代码扫描工具 七、持续集成工具 八、网络测试工具 九、app自动化工具 十、web安全测试工具 绵薄之力 引言 无论你是一名资深测试人员还是刚入行的新手&…

大数据实战 --- 世界新冠疫情数据分析

目录 开发环境 数据描述 功能需求 数据准备 统计计算 Hbase Hive 分析数据 开发环境 HadoopHiveSparkHBase 启动Hadoop&#xff1a;start-all.sh 启动zookeeper&#xff1a;zkServer.sh start 启动Hive&#xff1a; nohup hiveserver2 1>/dev/null 2>&1 &…

基于多种流量检测引擎识别pcap数据包中的威胁

在很多的场景下&#xff0c;会需要根据数据包判断数据包中存在的威胁。针对已有的数据包&#xff0c;如何判断数据包是何种攻击呢&#xff1f; 方法一可以根据经验&#xff0c;对于常见的WEB类型的攻击&#xff0c;比如SQL注入&#xff0c;命令执行等攻击&#xff0c;是比较容…

Radzen Blazor Studio 2.84 Crack

Radzen Blazor Studio 是一种桌面工具&#xff0c;它使 开发人员 能够创建漂亮的商业 Blazor 应用程序。快速地。 开放技术栈 没有供应商锁定。生成的源代码是人类可读的&#xff0c;您可以使用免费工具构建它。 Radzen 由流行的开源技术——ASP.NET Core、Blazor、Bootstrap …

Handler消息机制

App中一般多会有多个线程&#xff0c;多线程之间难免需要进行通信。开发中线程通信用的最多的就是Handler&#xff0c;另外还有&#xff0c;例如子线程进行数据处理&#xff0c;在主线程中进行UI更新。 当然了除了Handler这种通信方式外&#xff0c;线程间的通信还有其他几种方…

在线免费把Markdown格式文件转换为PDF格式

用CSDN的MarkDown编辑器在线转换 CSDN的MarkDown编辑器说实话还是挺好用的。 导出PDF操作步骤&#xff0c;图文配合看&#xff1a; 在MD编辑模式下写好MarkDown文章或者直接把要转换的MarkDown贴进来&#xff1b; 使用预览模式&#xff0c;然后在预览文件上右键选择打印&…

pycuda 安装出错解决

执行&#xff1a;pip install pycuda 出现&#xff1a;Building wheel for pycuda (PEP 517) … error 使用&#xff1a;pip install pycuda --no-binary :all: 不解决问题。 从源码编译 1、下载 pycuda-2021.1.tar.gz 2、tar xfz pycuda-2021.1.tar.gz 3、cd pycuda-20…

LNMP的部署

一、编译安装Nginx 服务 1、编译安装Nginx 服务的操作步骤 systemctl stop firewalld systemctl disable firewalld setenforce 01.1 安装依赖包 yum -y install pcre-devel zlib-devel gcc gcc-c make1.2 创建运行用户 useradd -M -s /sbin/nologin nginx1.3 编译安装 cd…

Shell编程(三)grep sed awk文本处理三剑客

上一章&#xff1a; Shell编程(二&#xff09;_做测试的喵酱的博客-CSDN博客 一、ps命令 指令&#xff1a; ps作用&#xff1a; 主要是查看服务器的进程信息选项含义&#xff1a; -e&#xff1a;等价于 ‘-A’ &#xff0c;表示列出全部的进程 -f&#xff1a;显示全部的列&am…

【珍藏版】SWAT模型十七项热点融合技术呈现,提升SWAT模型应用创新点

本次共十七个实践案例 1)遥感产品和SWAT模型快速建模 2)基于水文响应单元&#xff08;HRU&#xff09;的水资源时空分布特征 3)基于自定义流域与河道的SWAT模型建模与分析 4)子流域划分原理及其对模型不确定性的影响 5)坡度划分原理及其对模型不确定性的影响 6)DEM数据空…

站在程序猿的角度理解:UDP 协议

哈喽&#xff0c;大家好~我是你们的老朋友&#xff1a; 保护小周ღ&#xff0c;本期为大家带来的是 网络基础原理中的 UDP 协议&#xff0c;从什么协议&#xff1f;&#xff0c;认识 UDP 协议&#xff0c;UDP 的报文格式&#xff0c;UDP 传输大文件时的策略&#xff0c;以及 UD…

蓝库云|制造业该如何利用WMS仓库管理系统赋能企业发展

在数字化时代&#xff0c;制造业需要更加高效、智能、灵活地管理仓库&#xff0c;以满足市场的需求。WMS仓库管理系统作为一种先进的仓库管理工具&#xff0c;蓝库云认为WMS系统可以帮助制造企业实现数字化转型升级&#xff0c;提高仓库管理效率&#xff0c;降低成本&#xff0…

HuggingFace过去七天最流行的AI模型一览——预训练大模型绝对王者

HuggingFace是目前最火热的AI社区&#xff0c;很多人称之为AI模型的GitHub。包括Google、微软等很多知名企业都在上面发布模型。 HuggingFace简介&#xff1a;https://www.datalearner.com/blog/1051636550099750 而HuggingFace上提供的流行的模型也是大家应当关注的内容。本…

ChatGPT4写贪吃蛇游戏(Notion)[pygame的学习]

这里我使用的是Notion写出来的贪吃蛇&#xff0c;开始使用百度的文心一言来试下效果&#xff0c;生成了好几次的代码都是有bug&#xff0c;所以生成代码这块还得是ChatGPT。这篇主要就是了解下pygame库的一些方法&#xff0c;当然在没有安装这个库的&#xff0c;需要先安装&…

【浅谈 new 与 delete】

目录&#xff1a; 前言new 与 delete内置类型自定义类型operator new 与 operator deletenew 和 delete 实现原理定位new 总结 前言 打怪升级&#xff1a;第39天 在C语言中&#xff0c;我们动态申请内存的方法是使用malloc函数&#xff0c;它的同胞兄弟还有calloc 和realloc&a…

php使用tcpdf,通过html生成的pdf文件,合同章(图片)错位?需要怎么解决

php使用tcpdf&#xff0c;通过html生成的pdf文件&#xff0c;合同章有错位&#xff1f;需要怎么解决&#xff1f; 1、html下的排版正确&#xff0c;如图&#xff1a; 2、html代码&#xff0c;如图 3、生成pdf后的文件&#xff0c;如图 $pdf->Image()&#xff0c;计算一下x、…

【QT】详细介绍Qt的窗口属性:Qt::WA_DeleteOnClose属性

目录 1. close()2. WA_DeleteOnClose属性3. 测试3.1 设置了 Qt::WA_DeleteOnClose 属性3.2 未设置 Qt::WA_DeleteOnClose 属性 4. 测试代码 1. close() 当我们创建一个窗口&#xff08;MainWindow, Widget, Dialog, QMessageBox, 等等&#xff09;后&#xff0c;我们一般会调用…

matlab绘制折线图基本操作

本篇博客主要总结matlab绘制折线图的基本操作&#xff0c;使用的函数是plot函数&#xff0c;关于plot的函数语法规则&#xff0c;这里不再赘述&#xff0c;可以参考matlab官方文档&#xff0c;https://ww2.mathworks.cn/help/matlab/ref/plot.html#d124e1037051&#xff0c;不看…

GIS开源库GEOS库学习教程(三):空间关系/DE-9IM/谓词

1、DE-9IM 要判断两个多边形的关系&#xff0c;实际上属于几何图形空间关系判断。几何图形并不只有多边形一种&#xff0c;它包括点、线、面构成的任何图形&#xff0c;两两之间相互关系也有很多种&#xff0c;因此空间关系非常复杂。根据前人的研究&#xff0c;总结出了DE-9IM…

图论经典A-Star(A*) Algorithm最短路径,networkx,Python(1)

图论经典A-Star(A*) Algorithm最短路径&#xff0c;networkx&#xff0c;Python&#xff08;1&#xff09; A-Star Algorithm&#xff0c;即为A*&#xff08;A星&#xff09;算法&#xff0c;图的最短路径。 &#xff08;1&#xff09;A-Star(A*)算法需要事先知道起点和终点才…