【Java面试】泛型

news2024/12/29 9:22:11

文章目录

  • 说一说你对泛型的理解
  • 介绍一下泛型擦除
  • List<? super T>和List<? extends T>有什么区别?

说一说你对泛型的理解

Java集合有个缺点—把一个对象“丢进”集合里之后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型(其运行时类型没变)。
在这里插入图片描述
在这里插入图片描述

Java集合之所以被设计成这样,是因为集合的设计者不知道我们会用集合来保存什么类型的对象,所以他们把集合设计成能保存任何类型的对象,只要求具有很好的通用性。但这样做带来如下两个问题:

  • 集合对元素类型没有任何限制,这样可能引发一些问题。例如,想创建一个只能保存Dog对象的集合,但程序也可以轻易地将Cat对象“丢”进去,所以可能引发异常。

  • 由于把对象“丢进”集合时,集合丢失了对象的状态信息,只知道它盛装的是Object,因此取出集合元素后通常还需要进行强制类型转换。这种强制类型转换既增加了编程的复杂度,也可能引发ClassCastException异常。

从Java 5开始,Java引入了“参数化类型”的概念,允许程序在创建集合时指定集合元素的类型,Java的参数化类型被称为泛型(Generic)。例如 List< String >,表明该List只能保存字符串类型的对象。

有了泛型以后,程序再也不能“不小心”地把其他对象“丢进”集合中。而且程序更加简洁,集合自动记住所有集合元素的数据类型,从而无须对集合元素进行强制类型转换。

面试场景:
面试官:说说你对泛型的理解。

我:好的。我们知道,在我们使用集合的时候,集合默认是允许我们放入一个Object类型的对象的。而Java中所有的类都默认继承了Object类。因此其实所有的类都可以放入到集合中。

我:这就造成了一个问题,如果我们想要一个只能存放String类型的集合,那么可能我们放入String之后,又放入了Integer等类型。

我:并且我们在取出元素的时候,它的返回类型也是Object,那么此时我们就得显式的进行类型转换,提高了ClassCastException的可能性。

我:所以在JDK1.5之后,Java提供了一种“参数化类型的概念”,也就是我们说的泛型,他允许我们在使用集合的时候设定类型,而之后再向这个集合中添加或获取元素的时候,元素类型必须是这个类型的或者其子类。这样子我们就能自己控制集合中元素的类型了,也就无需在对元素进行强制类型转换。

我:以上是我对泛型的理解。

介绍一下泛型擦除

在严格的泛型代码里,带泛型声明的类总应该带着类型参数。但为了与老的Java代码保持一致,也允许在使用带泛型声明的类时不指定实际的类型。如果没有为这个泛型类指定实际的类型,此时被称作raw type(原始类型),默认是声明该泛型形参时指定的第一个上限类型。

当把一个具有泛型信息的对象赋给另一个没有泛型信息的变量时,所有在尖括号之间的类型信息都将被扔掉。比如一个
List < String > 类型被转换为List,则该List对集合元素的类型检查变成了泛型参数的上限(即Object)。

上述规则即为泛型擦除,可以通过下面代码进一步理解泛型擦除:

List<String> list1 = ...; List list2 = list1; // list2将元素当做Object处理

从逻辑上来看,List< String > 是List的子类,如果直接把一个List对象赋给一个List< String >对象应该引起编译错误,但实际上不会。对泛型而言,可以直接把一个List对象赋给一个 List< String > 对象,编译器仅仅提示“未经检查的转换”。

上述规则叫做泛型转换,可以通过下面代码进一步理解泛型转换:

List list1 = ...; List<String> list2 = list1; // 编译时警告“未经检查的转换”

List<? super T>和List<? extends T>有什么区别?

? 是类型通配符,List<?> 可以表示各种泛型List的父类,意思是元素类型未知的List;

List<? super T> 用于设定类型通配符的下限,此处 ? 代表一个未知的类型,但它必须是T的父类型;

List<? extends T> 用于设定类型通配符的上限,此处 ? 代表一个未知的类型,但它必须是T的子类型。

在Java的早期设计中,允许把Integer[]数组赋值给Number[]变量,此时如果试图把一个Double对象保存到该Number[]数组中,编译可以通过,但在运行时抛出ArrayStoreException异常。这显然是一种不安全的设计,因此Java在泛型设计时进行了改进,它不再允许把 List< Integer > 对象赋值给 List< Number > 变量。

数组和泛型有所不同,假设Foo是Bar的一个子类型(子类或者子接口),那么Foo[]依然是Bar[]的子类型,但G< Foo > 不是 G< Bar > 的子类型。Foo[]自动向上转型为Bar[]的方式被称为型变,也就是说,Java的数组支持型变,但Java集合并不支持型变Java泛型的设计原则是,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException异常。

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

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

相关文章

B站 全套java面试(200道)问题MD(题目+答案)

Java面向对象有哪些特征&#xff0c;如何应用 ​ 面向对象编程是利用类和对象编程的一种思想。万物可归类&#xff0c;类是对于世界事物的高度抽象 &#xff0c;不同的事物之间有不同的关系 &#xff0c;一个类自身与外界的封装关系&#xff0c;一个父类和子类的继承关系&…

ArcGIS基础实验操作100例--实验87计算矩形方向

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 空间分析篇--实验87 计算矩形方向 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&…

k8S集群切换IP

背景&#xff1a; 在实际交付场景中&#xff0c;有搬迁机房、网络未规划完成需要提前部署、客户使用DHCP分配IP、虚拟机IP更换等场景。目前统一的方案还是建议全部推到重新部署一套业务环境&#xff0c;存在环境清理不干净、重新部署成本较高、周期长、客户对产品能力质疑等问…

Mac - 通过 Script 实现更换桌面壁纸

目录 一.引言 二.OsaScript 实现自动换壁纸 1.切换壁纸脚本 2.定时获取 A.修改 Python 脚本 B.修改 Shell 脚本 C.添加 Crontab 三.Iterm2 更换背景 A.打开 Preferences B.选择 Profiles -> Window C.效果图 一.引言 前面介绍了通过 Python Crontab 实现 mac 上…

【分布式】浅谈CAP、BASE理论(1)

CAP理论 起源 CAP定理&#xff0c;又被称作布鲁尔定理。这个定理起源于加州大学柏克莱分校的计算机科学家埃里克布鲁尔在2000年的分布式计算原理研讨会上提出的一个猜想1。在2002年&#xff0c;麻省理工学院的赛斯吉尔伯特和南希林奇发表了布鲁尔猜想的证明&#xff0c;使之成…

Portraiture2023免费后期修图插件磨皮神器DR5

后期修图中有一个非常关键&#xff0c;而且不可或缺的步骤&#xff0c;那就是磨皮&#xff0c;磨皮的方法有很多种&#xff0c;但最方便快捷就能达到大片级效果的方法&#xff0c;莫过于使用磨皮插件了&#xff0c;Portraiture图像磨皮插件&#xff0c;支持PS CC- CC2023&#…

4.R语言【rehsape2包】介绍、melt( )、cast( )函数、其他使用技巧

b站课程视频链接&#xff1a; https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99&#x1f622;&#x1f622;元买了&#xff0c;感觉讲的没问题&#xff0c;就是知识点结构有点乱&#xff0c;有点废话&#xff09;&…

CAD转换PDF怎么转换?新手必备的方法

相信很多从事建筑类的相关工作的小伙伴们对CAD文件都并不陌生&#xff0c;在设计图纸和数据更改大都是使用这类文件的专业工具。这类文件的专业性较强设计出来的图纸也比较规范&#xff0c;但就有一个问题比较麻烦&#xff0c;那便是在不同设备打开需要对应的查阅软件&#xff…

【TypeScript】Ts基本概念

TypeScript基本概念 TypeScript 是什么&#xff1f; 目标&#xff1a;能够说出什么是typescript 内容&#xff1a; TS 官方文档TS 中文参考 - 不再维护 TypeScript 简称&#xff1a;TS&#xff0c;是 JavaScript 的超集&#xff0c;简单来说就是&#xff1a;JS 有的 TS 都有…

振弦采集模块参数配置工具的连接与断开

振弦采集模块参数配置工具的连接与断开 在指令区的【 COM 端口】组合框内操作完成。【端口】 下拉框&#xff1a;列出了本计算机当前已经存在的所有 COM 端口名称&#xff0c;若与模块连接的端口名称未在下拉框中列出&#xff0c;还可通过手工输入端口名的方法自由输入。 【速…

【NI Multisim 14.0原理图文件管理——新建设计文件】

目录 序言 一、原理图文件管理 二、新建设计文件 &#x1f34d;1. 空白文件 &#x1f34d; 2.系统安装模板文件 &#x1f34d;3. 自定义模板文件 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地使用虚拟元器件和仪器、仪表进行电路设…

C#,图像二值化(21)——局部阈值的韦尔纳算法(Wellner Thresholding)及源代码

1 韦尔纳算法&#xff08;Wellner Throsholding&#xff09;摘要针对计算大量缺陷时速度较慢且图像阈值不平滑的Wellner算法&#xff0c;本文提出了两种改进方案&#xff0c;第一种是一维平滑算法&#xff08;ODSA&#xff09;&#xff0c;第二种是基于第一种算法的&#xff0c…

《MYSQL实战45讲》笔记(11-20)

11&#xff1a;怎么给字符串字段加索引&#xff1f; 业务场景&#xff1a;基于字符串字段做查询。例如邮箱登录等等。 前缀索引的优势&#xff1a;相对于整个字段索引&#xff0c;前缀索引的占用空间更小。 前缀索引带来的问题&#xff1a;区分度过低的时候会额外扫描次数。 …

CATIA和CAD超全对比,来看看哪个好用

从文明伊始&#xff0c;绘图和制图就对人类发展发挥着重要作用&#xff0c;它通过图形表示使概念更容易理解&#xff0c;这导致了“工程艺术”的发展。绘图是一种使用图片和符号来呈现概念、想法或观点的方式&#xff0c;而绘图是任何现实世界对象或事物的图形表示。为了简化数…

1、Visual Studio 2017安装

目录 一、简介 二、安装步骤 三、Visual Studio 2017的使用 一、简介 Visual Studio是微软推出的一款C编译器&#xff0c;将“高级语言”翻译为“机器语言&#xff08;低级语言&#xff09;”的程序&#xff0c;VS是一个非常完整的开发工具集&#xff0c;包括了所有软件生命…

Vue2.0开发之——组件数据共享-父向子传值(38)

一 概述 组件之间的关系父向子传值子向父传值 二 组件之间的关系 2.1 组件之间的关系 在项目开发中&#xff0c;组件之间的最常见的关系分为如下两种 父子关系兄弟关系 2.2 父子组件之间的数据共享 父子组件之间的数据共享又分为: 父 -> 子共享数据子 -> 父共享数据…

070-JAVA项目实训:仿QQ即时通讯软件讲座五(讲解用户注册功能)

【上一讲】069-JAVA项目实训:仿QQ即时通讯软件讲座四(讲解系统登录功能)_CSDN专家-赖老师(软件之家)的博客-CSDN博客 本文主要内容是实现注册QQ用户功能,自动获取本机IP地址,与系统用户判断端口是否唯一,使用的主要技术如下: 1.使用数据库技术完成注册功能; 2.自动…

【Linux】线程概念

目录&#x1f308;前言&#x1f338;1、Linux线程概念&#x1f361;1.1、概念&#x1f362;1.2、线程的优点&#x1f367;1.3、线程的缺点&#x1f368;1.4、线程的异常和用途&#x1f33a;2、Linux下进程 vs 线程&#x1f308;前言 这篇文章给大家带来线程的学习&#xff01;…

渗透测试基础【01】——测试流程(IPC$)

渗透测试基础【01】——测试流程 注意&#xff0c;攻击对方需要对方授权&#xff0c;本文章目的只为教学&#xff0c;不要拿去干违法的事 1 渗透测试流程 授权&#xff08;获取目标用户授权&#xff0c;否则是违法行为&#xff09;信息收集 nslookup whois扫描漏洞 nmapip…

【前端代码高亮】页面代码高亮展示之Highlight高亮组件应用详解,附多个主题效果

【写在前面】作为前端开发的基本上都有接触这个高亮组件&#xff0c;这个也是目前被大家誉为最全面&#xff0c;体验最好的&#xff0c;所以针对数据展示型高亮显示我是力推这个的&#xff0c;但是我个人还是觉得还有不完美的地方&#xff0c;比如说一边输入一边高亮就不行了。…