我丢,去面试初级Java开发岗位,被问到泛型?

1、泛型的基础概念

1.1 为什么需要泛型

        List list = new ArrayList();//默认类型是Objectlist.add("A123");list.add("B234");list.add("C345");System.out.println(list);for(int i=0;i<list.size();i++){//若要将list中的元素赋给String变量,需要进行类型转换,不然会报Incompatible types错误,显示list.get(i)返回的是ObjectString str =  (String) list.get(i);System.out.println(str);}
​   list.add(123);//因为类型是Object,我们可以把Integer类型或者其他数据类型的元素也加入list之中System.out.println(list.get(3));for(int i=0;i<list.size();i++){//String str =  (String) list.get(i);//但是在这里会报错java.lang.ClassCastException,我们不能直接将Integer类型的数据转换成StringSystem.out.println(list.get(i).getClass());}

如代码中所示,当我们定义了一个List,list默认的类型是所有对象的基类Object,那么我们取出数据的时候需要经过一次类型转换才能进行对象的实际类型的相关操作。因为List中的类型是Object,那么我们先添加了String类型的数据,然后再添加Integer或者其他类型的数据也是允许的,因为编译时List中是Object类型的数据,然而运行的时候却是它本身的类型,所以当我们将List中的数据当作String处理时会抛出java.lang.ClassCastException

那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现java.lang.ClassCastException异常呢?答案就是使用泛型。

1.2 什么是泛型

Java泛型设计原则是:只要在编译时期没有出现警告,那么运行时期就不会出现ClassCastException异常。

泛型,即“参数化类型”,把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊类型,把<数据类型>当作是参数一样传递。

相关术语:

  • ArrayList中的E称为类型参数变量

  • ArrayList中的Integer称为实际类型参数

  • 整个称为ArrayList泛型类型

  • 整个ArrayList称为参数化的类型ParameterizedType

泛型的作用:

  • 代码更加简洁【不用强制转换】

  • 程序更加健壮【只要编译时期没有警告,那么运行时就不会抛出ClassCastException的异常】

  • 可读性和稳定性【在编写集合的时候,就限定了类型】

        List<String> strlist = new ArrayList<String>();List<Integer> intlist = new ArrayList<Integer>();
​strlist.add("A");strlist.add("B");//strlist.add(123);//编译时报错for(String str:strlist){System.out.println(str);//A//B}//加入Java开发交流君样:756584822一起吹水聊天System.out.println(strlist.getClass());//class java.util.ArrayListSystem.out.println(intlist.getClass());//class java.util.ArrayListSystem.out.println(strlist.getClass()==intlist.getClass());//true

泛型擦除

泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛型的java程序后生成的class文件中将不再带有泛型信息,以此使程序的运行效率不受到影响,这个过程称之为“擦除”。

泛型这个概念是JDK5提出的,JDK5以前的版本是没有泛型的,需要建通JDK5以下的集合。当把带有泛型特性的集合赋值给老版本的集合的时候,会把泛型给擦除了,它保留的是类型参数的上限,即Object。而当我们将没有类型参数的集合赋给带类型参数的集合,也不会报错,仅仅是会提示“未经检查的转换(Unchecked assignment)”,甚至也可以将它赋给其他不同类型的带有泛型特性的集合,只是依旧会抛出ClassCastException异常。

        //类型被擦除了,保留的是类型的上限,String的上限就是ObjectList list = strlist;
​List<String> stringList2 = list;List<Integer> intList2 = list;//你也可以把它赋给Integer类型的集合,但是当你把这个集合当成Integer的集合操作的时候,依旧会抛出ClassCastException异常for (Integer i:intList2){//java.lang.ClassCastExceptionSystem.out.println(i);}

3、泛型的定义和使用

3.1 泛型类\泛型接口

泛型类、泛型接口就是把泛型定义在类或者接口上,在用户使用该类的时候才把类型明确下来。我们常用的集合,List,Map<K,V>,Stack……就是泛型类。在类上定义的泛型,在泛型类的方法、变量中都可以使用。

由于类型参数变量T在java泛型中仅仅是一个占位符,在传递参数之后才能使用,即在完成实例创建之后才能使用,所以在泛型类中,不能定义包含泛型类型的静态变量和静态方法,会报错cannot be referenced from a static context。泛型类中包含泛型类型的变量和方法必须在创建了实例明确了传递的类型参数后才可以使用。

class Myset<T>{private T value;//public static T sval;//cannot be referenced from a static contextpublic static int sval2;public Myset(){}
​public Myset(T val){this.value = val;}
​public void setValue(T value) {this.value = value;}
​public T getValue() {return value;}/* public static T getSval(){//cannot be referenced from a static contextreturn sval;}*/
}Myset<String> myset = new Myset<>();myset.setValue("12345");System.out.println(myset.getValue());//12345
​myset = new Myset<>("23");System.out.println(myset.getClass());//class liwx.learning.Myset

3.2 泛型方法

 public static  <T> void PrintArray(T [] arr){System.out.print("[");for(T t:arr){System.out.print(t+",");}System.out.println("]");}
Integer[]  a = {1,2,3,4,5,6,7};
PrintArray(a);//[1,2,3,4,5,6,7,]

3.3 泛型类的继承

泛型类的子类有两种继承方式

  • 子类不明确泛型类的参数变量,子类也是泛型类

  • 子类明确泛型类的参数变量,子类不是泛型类

//子类不明确泛型类的参数变量,子类也是泛型类
class MyChiSet1<T> extends Myset<T>{public MyChiSet1(){}public MyChiSet1(T val){super(val);}}
//子类明确泛型类的参数变量,子类不是泛型类
class MyChiSet2 extends Myset<String>{public MyChiSet2(){}public MyChiSet2(String val){super(val);}
}

3.4 类型通配符?及其上下限

通配符<?>和类型参数变量的区别是什么?通配符<?>是实参而不是类型形参,而且List<?>在逻辑上是List,List等所有List<具体类型实参>的父类,它的使用比类型形参T更加灵活,但传入的通配符通常进行的是许多于具体类型无关的操作,如果涉及到具体类型相关的操作,以及返回值,还是需要使用泛型方法T。

当我们使用?号通配符的时候,只能调用与对象无关的方法,不能调用对象与类型有关的方法。因为直到外界使用才知道具体的类型是什么。

//虽然Object是所有类的基类,但是List<Object>在逻辑上与List<Integer>等并没有继承关系,这个方法只能传入List<Object>类型的数据 public static void showOList(List<Object> list){System.out.println(list.size());}//同理,这个方法只能传入List<Number>类型的数据,并不能传入List<Integer>public static void showList(List<Number> list){System.out.println(list.size());}//加入Java开发交流君样:756584822一起吹水聊天//使用通配符,List<?>在逻辑上是所有List<Number>,List<Integer>,List<String>……的父类,可以传递所有List类型的数据,但是不能在List<?>类型的数据进行于具体类型相关的操作,如addpublic static void showList2(List<?> list){System.out.println("<?>");System.out.println(list.size());}//设置通配符上限,可以传入List<Number及Number的子类>public static void showNumList(List<? extends Number> list){System.out.println(list.size());}//设置通配符上限,List<? super Number>只可以传入List<Number及其父类>public static boolean Compare(List<? super Number> list1,List<? super Integer> list2){return list1.size()>list2.size();}
     List<Integer> Intgetlist = new ArrayList<>();List<Number> Numberlist = new ArrayList<>();//虽然Number是Integet的父类,但是传入List,它们逻辑上没有了继承关系System.out.println(Intgetlist.getClass()==Numberlist.getClass());//true//加入Java开发交流君样:756584822一起吹水聊天//showList(java.util.List<java.lang.Number>)//List<Integer>和List<Number>逻辑上无继承关系,所以无法调用//showList(Intgetlist);//showList(java.util.List<java.lang.Number>)in FXtest cannot be applied to(java.util.List<java.lang.Integer>)showList(Numberlist);//public static void showList2(List<?> list)//通配符List<?>在逻辑上是所有List<具体参数类型>的父类,方法可以传入其子类类型的数据showList2(Intgetlist);showList2(Numberlist);// public static void showNumList(List<? extends Number> list)//当设定了通配符上限,只能传入List<Number及其子类>的数据List<String> Stringlist = new ArrayList<>();showNumList(Intgetlist);showNumList(Numberlist);//showNumList(Stringlist);//showNumList(java.util.List<? extends java.lang.Number>)in FXtest cannot be applied to(java.util.List<java.lang.String>)
​
​//public static boolean Compare(List<? super Number> list1,List<? super Integer> list2)//当设定了通配符下限,List<? super Number>只能传入List<Number及其父类>的数据,不能传入子类Integer的List,// 而List<? super Integer>则可以传入其父类Number的List//Compare(Intgetlist,Numberlist);Compare(Numberlist,Intgetlist);

通配符的使用在逻辑上还原了泛型类传入数据类型的参数父类子类的继承关系,同时也可以按照需求设定通配符的上限了下限。

  • List<?>在逻辑上是所有List<具体参数类型>的父类,可对所有List数据进行操作

  • List<? extends Type>设定了通配符的上限,可对所有Type及Type的子类进行操作

  • List<? super Type>设定了通配符的下限,可对所有Type及Type的父类进行操作

最后,祝大家早日学有所成,拿到满意offer

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

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

相关文章

xp下设置文件的权限(转)

第一步&#xff1a; 1&#xff0c;我的电脑&#xff0d;&#xff0d;工具&#xff0d;&#xff0d;文件夹选项&#xff0d;&#xff0d;查看 去掉”使用简单文件共享”的选中状态&#xff0e;确定 第二步&#xff1a; 右击 D 盘 &#xff0d;&#xff0d; 安全 &#xff0d;&am…

echart 地图 某个地区_中国饮食地图来袭!你爱的口味暗藏健康隐患吗?

食&#xff0c;既是人生存之根本&#xff0c;也是人们热爱生活的体现。中国地域广阔、物产富饶&#xff0c;中国人对“吃”看重也愿钻研&#xff0c;种种因素造就了中国美食 “百花齐放”的局面&#xff0c;在“吃货”眼里&#xff0c;中国地图俨然就是一张美食地图。不同地区的…

面试官:实现一个带值变更通知能力的Dictionary

如题&#xff0c; 你知道字典KEY对应的Value什么时候被覆盖了吗&#xff1f;最近大家都在追.Net6 update&#xff0c;咱还是保持节奏&#xff0c;通用语言聊技术。没背景说个铲铲上文中 数据获取组件维护了业务方所有(在用)的连接对象&#xff0c;DBA能在后台无侵入的切换备份库…

颠覆认知!完美赌徒,到底是如何用数学打造经济神话?!

▲ 点击查看说起世界上最会赚钱的数学家&#xff0c;非詹姆斯西蒙斯莫属。1938年&#xff0c;西蒙斯出生于美国的马萨诸塞州&#xff0c;是一个鞋厂的儿子。在其他的孩子&#xff0c;还在听童话故事的时候&#xff0c;西蒙斯就已经开始展露出惊人的数学天赋了。3岁的时候&…

数据源的配置和使用 视频下载

[浪曦][原创][A362]数据源的配置和使用(BLing原创)&#xff0c;请用迅雷下载&#xff0c;可能需要注册&#xff01; 包括servlet调用数据源&#xff0c;spring调用数据源转载于:https://blog.51cto.com/huqianhao/955256

ubuntu apt-get常用命令

常用的APT命令参数   apt-cache search package 搜索包   apt-cache show package 获取包的相关信息&#xff0c;如说明、大小、版本等   sudo apt-get install package 安装包   sudo apt-get install package - - reinstall 重新安装包   sudo apt-get -f ins…

abs函数的使用方法 oracle_SQL Server 常用函数使用方法

1、SubString()&#xff1a;用于截取指定字符串的方法。该方法有三个参数&#xff1a;参数1&#xff1a;用于指定要操作的字符串。参数2&#xff1a;用于指定要截取的字符串的起始位置&#xff0c;起始值为 1 。参数3&#xff1a;用于指定要截取的长度。select substring(abcde…

高考落榜怎么办,奉劝学弟学妹们一些事情,请一定要擦亮眼睛

在目前这个社会情况Java技术是当前社会的一个热门专业&#xff0c;无论是pc端还是移动端对java的需求都是最多的&#xff0c;大学生学java正好顺应时代的发展&#xff0c;不仅有钱途还有前途&#xff0c;Java也适合零基础的人学习。 最近看见一句话 高考不努力&#xff0c;学习…

url地址传参中文乱码处理

1.将字符串转码&#xff1a;new String(“xxxxx”.getBytes("iso-8859-1"),"utf-8") 这种转码方式有很大的弊端&#xff0c;因为它是使用指定的字符集将此String 编码为 byte 序列&#xff0c;并将结果存储到一个新的 byte 数组中&#xff0c;然后…

神仙打架!一人公开单挑全欧洲数学家,却惨遭4位数学家大反转,66年的难题被一晚破解......

全世界只有3.14 % 的人关注了青少年数学之旅两点之间直线最短&#xff0c;这家喻户晓的数学名言&#xff0c;就算是学渣也能倒背如流。但学渣们不知道的是&#xff0c;这条直线并不是最快的。为了让学渣们真正理解这句话&#xff0c;今天&#xff0c;超模君决定科普一波起源关于…

基于事件驱动架构构建微服务第4部分:repositories

原文链接&#xff1a;https://logcorner.com/building-microservices-through-event-driven-architecture-part4-repositories/在本文中&#xff0c;我将实现Repositories的命令端。存储库属于Clean架构的接口适配器在这一步中&#xff0c;我将开始实现基础设施的命令端&#x…

小松

之前做过一次小小的介绍(没看过的请参看此文&#xff1a;闲话小松)&#xff0c;相信不少老朋友应该都知道我是谁了。还不认识我的朋友可以称呼我小松(这名号有年头了&#xff0c;听习惯了^_^)&#xff0c;当然你喜欢怎么喊都成&#xff1a;)偶是个是理想主义的倡导者&#xff0…

vlan后 出现 outlook 正在试图从服务器检索数据

vlan后 出现 outlook 正在试图从服务器检索数据 cisco vlan outlook 正图试从Microsoft Exchange Server 检索数据。cisco 3750 vlan outlook is retrieving data from Microsoft Exchange Server mail.abc.com 最近对公司的网络按需要划分了基出802.1q的VLAN&#xff0c;…

二面京东,面试官直接问我JVM,我心里一阵暗爽~

二面京东&#xff0c;面试官直接问我JVM&#xff0c;我心里一阵暗爽~简直了&#xff0c;hhhh明人不说暗话&#xff0c;直接进入主题&#xff01;&#xff01;&#xff01;一、什么是JVM二、JAVA代码编译和执行过程类加载机制类执行机制三、JVM内存管理和垃圾回收垃圾回收按照基…

最后的代课老师———漆红玉[转]

1月31日凌晨6点我们从渭源县城出发&#xff0c;天还未亮。1月的甘肃干冷干冷的&#xff0c;我们是在半路上接的漆老师&#xff0c;刚开始我以为是寇筱茜老师的一个熟人&#xff0c;路上寇老师才和我说漆老师也是代课老师。寇筱茜老师有一句名言&#xff1a;每一个代课老师都有一…

ae渲染出现错误是什么问题_[Switch]解决OPENWRT路由,使用UU加速器等出现相同IP,DNS解析错误问题...

本文在之上添加DNS解析错误的解决方案解决 NS openwrt路由器 开腾讯 UU之类的加速器无法上网的问题​tieba.baidu.com将子网掩码转换为二进制&#xff0c;即为11111111.11111111.0.0&#xff0c;1有16位&#xff0c;令x16&#xff1b;IP地址若为aaa.bbb.ccc.ddd&#xff0c;设置…

程序员从入门到升级,或许可以看一看这几个公众号

全世界只有3.14 % 的人关注了青少年数学之旅快节奏的现代社会中&#xff0c;每个人都疲于奔命&#xff0c;“丧、累、太难了”已成为成年人的生活主题。难得的闲暇时间&#xff0c;公众号是不可或缺的消遣方式。但我们被海量数据淹没&#xff0c;越来越多的公众号只是消耗情绪&…

浅谈C#取消令牌CancellationTokenSource

前言相信大家在使用C#进行开发的时候&#xff0c;特别是使用异步的场景&#xff0c;多多少少会接触到CancellationTokenSource。看名字就知道它和取消异步任务相关的&#xff0c;而且一看便知大名鼎鼎的CancellationToken就是它生产出来的。不看不知道&#xff0c;一看吓一跳。…

jquery预加载

$(function(){});DOM创建完成就开始加载JS代码。 $(window).load(function(){});所有资源都下载好以后再开始加载JS代码。转载于:https://www.cnblogs.com/invincible-hehe/p/3886581.html

C# 向Main函数传递参数(程序启动时传递参数)

代码 staticvoidMain(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);if(args.Length!0) { Application.Run(newF_WebIE(args[0])); }else{ Application.Run(newF_WebIE(null)); } }注意&#xff1a;不能把 参数 s…