【什么是泛型,有什么好处】

在这里插入图片描述

✅什么是泛型,有什么好处

  • ✅典型回答
  • ✅泛型是如何实现的
    • ✅什么是类型擦除?
    • 📝C语言对泛型的支持
    • 📝泛型擦除的缺点有哪些?
  • ✅对泛型通配符的理解
    • 📝泛型中上下界限定符 extends 和 super 有什么区别?
    • ✅List<?>,List<Object>,List之间的区别?
    • ✅在泛型为Integer的ArrayList中存放一个String类型的对象
    • ✅对数组协变和泛型非协变的理解

✅典型回答

Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(typeparameter)。声明的类型参数在使用时用具体的类型来替换。泛型最主要的应用是在JDK 5中的新集合类框架中。




泛型的好处有两个:


1、方便: 可以提高代码的复用性。以List接口为例,我们可以将String、Integer等类型放入List中,如不用泛型,存放String类型要写一个List接口,存放Integer要写另外一个List接口,泛型可以很好的解决这个问题。


2、安全: 在泛型出之前,通过Object实现的类型转换需要在运行时检查,如果类型转换出错,程序直接GG,可能会带来毁灭性打击。而泛型的作用就是在编译时做类型检查,这无疑增加程序的安全性。


✅泛型是如何实现的


Java中的泛型通过类型擦除的方式来实现,通俗点理解,就是通过语法糖的形式,在java->.class转换的阶段,将List擦除调转为List的手段。换句话说,Java的泛型只在编译期,Jm是不会感知到泛型的。

✅什么是类型擦除?


类型擦除是Java在处理泛型的一种方式,如Java的编译器在编译以下代码时:


public class Foo<T> {
	T bar;
	void doSth(T param) {
		
	}
};
Foo<String> f1;
Foo<Integer> f2;

在编译后的字节码文件中,会把泛型的信息擦除掉:


public class Foo {
	Object bar;
	void dosth(Object param) {
	}
};

也就是说,在代码中的Foo 和 Foo使用的类,经过编译后都是同一个类。


所以说泛型技术实际上是Java语言的一颗语法糖,因为泛型经过编译器处理之后就被擦除了。


这种擦除的过程,被称之为一类型擦除。所以类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且在必要的时候添加类型检查和类型转换的方法。


类型擦除可以简单的理解为将泛型iava代码转换为普通iava代码,只不过编译器更直接点,将泛型iava代码直接转换成普通iava字节码。


📝C语言对泛型的支持


泛型是一种编程范式,在不同的语言和编译器中的实现和支持方式都不一样。


通常情况下,一个编译器处理泛型有多种方式,在C++中,当编译器对以下代码编译时。

template <typename T> struct Foo {
	T bar;
	void doSth(T param) {
		
	}
};

Foo<int> f1;
Foo<float> f2;

当编译器对其进行编译时,编译器发现要用到Foo和Foo,这时候就会为每一人泛型类新生成一份执行代码。相当于新创建了如下两个类:


struct FooInt {
	int bar;
	void doSth(int param) {
	}
};

struct FooFloat {
	float bar;
	void doSth(float param) {
	}
};

这种做法,用起来的时候很方便,只需要根据具体类型找到具体的的类和方法就行了。但是问题是,当我们多次使用不同类型的模板时,就会创建出来的很多新的类,就会导致代码膨胀。

📝泛型擦除的缺点有哪些?


1.泛型不可以重载


2.泛型异常类不可以多次catch


3.泛型类中的静态变量也只有一份,不会有多份。


✅对泛型通配符的理解


📝泛型中上下界限定符 extends 和 super 有什么区别?


<? extends T>表示类型的上界,表示参数化类型的可能是T 或是 T的子类。

// 定义一个泛型方法,接受任何继承自Number的类型
public <T extends Number> void processlumber(T number) {
	// 在这个方法中,可以安全地调用Number的方法
	double value = number .doubleValue( );
	// 其他操作...
}

<? super T> 表示类型下界 (Java Core中叫超类型限定),表示参数化类型是此类型的超类型 (父类型),直至Obiect

//定义一个泛型方法,接受任何类型的List,并向其中添加元素
public <T> void addElements(List<? super T> list, T element) {
	list.add(element);
	// 其他操作...
}

在使用限定通配符的时候,需要遵守PECS原则,即producer Extends,Consumer Super; 上界生产,下界消费。


如果要从集合中读取类型T的数据,并目不能写入,可以使用 ? extends 通配符;(Producer Extends),如上面的processNumber方法。


使用extends 的时候是可读取不可写入,那为什么叫上界生产呢?
答:因为这个消费者/生产者描述的<集合>,当我们从集合读取的时候,集合是生产者。




如果既要存又要取,那么就不需要使用任何的通配符。


✅List<?>,List,List之间的区别?

1、List<?>是一个末知类型的List,而List < object> 其实是任意类型的List。可以把List< String>,List< Integer>赋值给List<?>,却不能把List< String>赋值给 List< Object>。
2、可以把任何带参数的类型传递给原始类型List,但却不能把List< String>赋值给List< Obiect>,因为会产生编译错误(不支持协变)

✅在泛型为Integer的ArrayList中存放一个String类型的对象


通过反射可以实现:


public void test() throws Exception {
	ArrayList<Integer> list = new ArrayList<Integer>();
	Method method = list.getClass().getMethod("add"Object.class);
	method.invoke(list,"Java反射机制实例”);
	System.out.println(list.get(0));
}

✅对数组协变和泛型非协变的理解


所胃协变,可以简单理解为因为Object是String的父类,所以Object1同样是Stringl的父类,这种情况Java是允许的;但是对于泛型来说,List< Obiect>和List< String>半毛钱关系都没有


为什么要这样设计呢,如果泛型允许协变(实际上以下代码第一步就会编译失败),考虑如下例子:


List<Object> a = new List<String>();
a.add(1); // 允许协变,可以装进来
String s = a.get(0); // 编译报错

但是,为什么泛型不允许协变,而数组允许协变呢? 原因有二 :


1 . 因为数组设计之初没有泛型,为了兼容考虑,如 Arrays.equals(object[],object[]) 方法,是时代无奈的产物

2 . 数组也属于对象,它记录了引用实际的类型,再放入数组的时候,如果类型不一样就会报错,而不是等到拿出来的时候才发现问题,相对来说安全一些。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于ssm二手车交易平台的设计论文

摘 要 进入21世纪网络和计算机得到了飞速发展&#xff0c;并和生活进行了紧密的结合。目前&#xff0c;网络的运行速度以达到了千兆&#xff0c;覆盖范围更是深入到生活中的角角落落。这就促使二手交易网站的发展。二手交易网站可以实现远程购物&#xff0c;远程选择喜欢的商品…

RocketMQ高级原理:深入剖析消息系统的核心机制

一、基础概念&#xff1a; 1. 消息模型 RocketMQ基于Producer、Broker、Consumer三部分构建。其中&#xff0c;Producer负责生成消息&#xff0c;Consumer处理消息&#xff0c;而Broker则承担消息存储的角色。Broker服务器可以存储多个Topic的消息&#xff0c;并支持消息在不同…

2000-2023年逐年最大NDVI数据集(500m)

2000-2023年逐年最大DNVI数据集&#xff08;500m&#xff09; 植被指数&#xff08;NDVI, Normalized Difference Vegetation Index&#xff09;可以准确反映地表植被覆盖状况。目前&#xff0c;NDVI时序数据已经在各尺度区域的植被动态变化监测、土地利用/覆被变化检测、宏观植…

Java 面试 多线程遇到的问题,如何处理

问题描述 某服务在运行过程中抛出了 RejectedExecutionException。 配置参数&#xff1a; corepoolsize 50, maxpoolsize 50&#xff0c; workqueue 为 SynchronousQueue 现象&#xff1a; 当新的task被拒绝时&#xff0c;pool size未达到配置值50. Caused by: java.util.conc…

MapReduuce配置YARN集群部署并启动(非常详细!!)

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f618;《CTF专栏》超级详细的解析&#xff0c;宝宝级教学让你从蹒跚学步到健步如飞&#x1f648; &#x1f60e;《大数据专栏》大数据从0到秃头&#x1f47d;&…

智能变电站协议系列-1、GOOSE、SV、MMS协议简介及GOOSE示例运行问题(IEC61850)

文章目录 一、前言二、资料准备三、智能变电站自动化系统架构四、GOOSE、MMS、SV协议以及其他协议1、GOOSE&#xff08;通用面向对象变电站事件&#xff09;协议2、MMS&#xff08;制造消息规范&#xff09;协议3、采样值 (SV) 协议4、数字化变电站中使用的其他协议遗留协议 五…

LangChain 29 调试Debugging 详细信息verbose

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

《工具箱-SVN》SVN安装、备份、迁移教程

文章目录 一、服务器搭建SVN1.检查SVN是否存在2.安装SVN3.创建版本库4.创建版本库存放文件地址5.修改配置文件5.1 vim authz5.2 vim passwd5.3 vim svnserve.conf 6.启动并查看SVN7.SVN Checkout8.SVN Update9.SVN Commit 二、SVN-无法连接主机&#xff0c;目标计算机积极拒绝&…

学鸿蒙开发的过程,差点要了我的命!

我真的好想感慨一下&#xff0c;这个世界真的给计算机应届生留活路了吗&#xff1f; 看着周围的同学&#xff0c;打算搞前端、JAVA、C、C的&#xff0c;一个两个去跑去应聘。你以为是00后整治职场&#xff1f; 真相是主打一个卑微&#xff1a;现阶段以学习为主&#xff08;工资…

centos安装Jenkins并拉取git远程仓库的代码进行自动化构建部署

安装Jenkins并拉取git远程仓库的代码进行自动化构建部署 1 前置条件2 先安装jdk113 安装git4 安装maven5 安装jenkins5.1下载jenkins5.2启动jenkins 6 使用jenkins拉取git仓库代码并部署6.1 安装插件6.2 在jenkins中配置maven6.3在jenkins上构建maven项目6.4 配置拉取的git仓库…

基于thinkphp+vue的大学生校园生活服务平台sb00r

大学生一体化服务平台可以提高大学生综合服务信息管理问题的解决效率&#xff0c;优化大学生综合服务信息处理流程&#xff0c;保证大学生综合服务信息数据的安全&#xff0c;它是一个非常可靠&#xff0c;非常安全的应用程序。 运行环境:phpstudy/wamp/xammp等 开发语言&#…

testtest

Python字符串格式化 c&#xff0c;c。 (笔记模板由python脚本于2023年12月19日 18:16:40创建&#xff0c;本篇笔记适合初通Python&#xff0c;熟悉六大基本数据(str字符串、int整型、float浮点型、list列表、tuple元组、set集合、dict字典)的coder翻阅) 【学习的细节是欢悦的历…

BW 抽取数据初始化

今天抽取几个销售订单的数据一直不对 &#xff0c;se14 清理了BW上的数据&#xff0c;发现重新抽数&#xff0c;抽取的数据跟ERP对不上&#xff0c;缺了好多&#xff0c;需要促使化&#xff0c;过程如下 。 感谢罗老师的支持 1.初始化 后勤类数据源&#xff0c;如果要重新…

鸿蒙介绍和基础环境搭建

1、鸿蒙介绍 鸿蒙系统&#xff1a;是华为公司2019年8月9日正式发布的操作系统&#xff0c;一款面向全场景的分布式操作系统&#xff0c;将人、设备、场景有机地联系在一起&#xff0c;将消费者在全场景生活中接触的多种智能设备进行资源共享&#xff0c;极速互联。 2020年9月1…

MT6785|MTK6785安卓核心板功能规格介绍_Helio G95核心板

MT6785安卓核心板是一款功能强大的工业级4G智能模块&#xff0c;它采用了Android 9.0操作系统。该核心板内置了蓝牙、FM、WLAN和GPS模块&#xff0c;具有高度集成的基带平台&#xff0c;结合了调制解调器和应用处理子系统&#xff0c;以支持LTE/LTE-A和C2K智能终端应用。 MTK67…

Http---HTTP响应报文

1. HTTP响应报文分析 HTTP 响应报文效果图: 响应报文说明: --- 响应行/状态行 --- HTTP/1.1 200 OK # HTTP协议版本 状态码 状态描述 --- 响应头 --- Server: Tengine # 服务器名称 Content-Type: text/html; charsetUTF-8 # 内容类型 Transfer-Encoding: chunked # 发送给客…

NAS下2023年最常用的Docker服务

服务推荐 密码服务&#xff08;bitwarden&#xff09; 我就属于从来记不住密码的那种人&#xff0c;这服务对我来说简直就是救星&#xff01; 之前我是国内应用统一一个密码&#xff0c;国外应用统一一个密码&#xff0c;密码中必须加特殊符号的一个密码&#xff0c;等等…这…

Android Studio 显示前进后退按钮

在写代码的过程中我们经常需要快速定位到先前或者往后的代码位置&#xff0c;可以使用Alt左右箭头 但是新安装的Android Studio工具栏上是没有显示左右箭头的工具按钮的&#xff0c;需要我们设置将Toolbar显示出来 View-Appearance-Toolbar 勾选即可 显示后

MATLAB - 机器人逆运动学设计器(Inverse Kinematics Designer APP)

系列文章目录 前言 一、简介 通过逆运动学设计器&#xff0c;您可以为 URDF 机器人模型设计逆运动学求解器。您可以调整逆运动学求解器并添加约束条件&#xff0c;以实现所需的行为。使用该程序&#xff0c;您可以 从 URDF 文件或 MATLAB 工作区导入 URDF 机器人模型。调整逆…