java泛型中占位符T和?有什么区别
作者:胖子爱你520 发布时间:2022-07-05 02:53:56
泛型中占位符T和?有什么区别?这是一个好问题,有的人可能弄不清楚,所以我们这里简单的演示一下,相信大家一定能弄清楚的!
先上两段代码:
public static <T> void show1(List<T> list){
for (Object object : list) {
System.out.println(object.toString());
}
}
public static void show2(List<?> list) {
for (Object object : list) {
System.out.println(object);
}
}
可以看到show1方法中我们使用了T,大家都知道这是泛型的常见写法,那么这里的T指的是某一类具体的对象,list集合里只能存放同一类型数据,如果插入不同类型数据则会报错。
那么show2方法中我们使用的是?,可以看到在void前面并没有<T>
,?可以表示成占位符,它自己也不知道list集合中会存放多少种类型的数据,所以这样就表明我们的list中存放N种数据类型也是可以的。
我们通过一段测试代码来直观的感受一下二者的区别吧:
public static void test(){
List<Student> list1 = new ArrayList<>();
list1.add(new Student("zhangsan",18,0));
list1.add(new Student("lisi",28,0));
list1.add(new Student("wangwu",24,1));
//这里如果add(new Teacher(...));就会报错,因为我们已经给List指定了数据类型为Student
show1(list1);
System.out.println("************分割线**************");
//这里我们并没有给List指定具体的数据类型,可以存放多种类型数据
List list2 = new ArrayList<>();
list2.add(new Student("zhaoliu",22,1));
list2.add(new Teacher("sunba",30,0));
show2(list2);
}
来看看运行结果:
Student{name='zhangsan', age=18, sex=0}
Student{name='lisi', age=28, sex=0}
Student{name='wangwu', age=24, sex=1}
************分割线**************
Student{name='zhaoliu', age=22, sex=1}
Teacher{name='sunba', age=30, sex=0}
从show2方法可以看出和show1的区别了,list2存放了Student和Teacher两种类型,同样可以输出数据,所以这就是T和?的区别啦~小伙伴们了解了吧
下面来看看?的扩展写法:
List<? extends 数据类型> list
public static void show3(List<? extends Teacher> list) {
for (Object object : list) {
System.out.println(object);
}
}
List<? extends Teacher> list
这种写法表示可以接收Teacher和它的子类数据类型的list集合,写个测试方法show3(list2);
试试:
Student{name='zhaoliu', age=22, sex=1}
Teacher{name='sunba', age=30, sex=0}
可以看到正常输出,因为集合中的数据都是Teacher的子类类型,如果我们将List<? extends Teacher> list
改成List<? extends Student> list
会出现什么情况?
仔细看这张图,我们新建了一个list3并且声明数据类型为Teacher,这个时候调用show3(List<? extends Student> list)
就马上会报错的,错误信息提示Teacher不能转换成Student,因为Student是Teacher的子类,而我们只接受Student及它的子类,所以当然会报错了。
List<? super 数据类型> list
这种写法表示只接收指定的数据类型及它的父类类型,也简单的写段代码看看效果:
public static void show4(List<? super Student> list) {
for (Object object : list) {
System.out.println(object);
}
}
可以看出来,我们接收的是Student及它父类的集合,我们写两个集合数据然后调用试试。
List list4 = new ArrayList<>();
list4.add(new Student("sunba",30,0));
list4.add(new Teacher("zhaoliu",22,1));
show4(list4);
在list中插入了一个Student和Teacher对象,看看结果:
Student{name='sunba', age=30, sex=0}
Teacher{name='zhaoliu', age=22, sex=1}
没毛病,正常运行并输出。
下面我们来看看,如果我们是传递的 Student的子类的集合会咋样
可以看到和之前的一样,会报错,理由也是一样的,以为我们已经定义了只能接收Student及其父类的数据类型。
最后来看一种情况
如果我定义List的时候没有指定数据类型,并且插入了一个Child,Student,Teacher,还是调用show4(List<? super Student> list)
,会报错吗?不会报错,运行结果又会是什么呢?
可以看到这样并没有报错,因为list可以存放多种数据类型,那么调用show4方法时会是什么结果呢?
可以看到程序正常运行并输出结果,注意一点,我们接收的是Student及其父类对象数据类型,因为我们的Child是继承Student的,所以程序自动将我们的Child转成父类Student进行输出,所以大家要注意这一点,会自动向上转化。
来源:https://blog.csdn.net/woshizisezise/article/details/79374460


猜你喜欢
- 介绍try-with-resources是Java中的环绕语句之一,旨在减轻开发人员释放try块中使用的资源的义务。它最初在Java 7中引
- 用的Idea,在写MyBatis时,测试发现有以下的报错信息Error parsing SQL Mapper Configuration.
- * 什么是 * Spring MVC中的 * (Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户
- 一、Stream流简单示例需求:按照要求集合创建和遍历创建一个结合,存储多个字符串元素把集合中所有以"张"开头的元素存储
- 本文实例为大家分享了C#实现围棋游戏的具体代码,供大家参考,具体内容如下之所以选择围棋作为大作业一方面是想挑战一下,另一方面是由于从6岁学围
- 目录1.文件读写1.1打开文件1.2关闭文件1.3读取文件1.4写入文件1.5读写二进制I/O文件1.6获取文件的大小1.7文本简单加密、解
- 有想过hash["A1"] = DateTime.Now;这句是怎么实现的吗?我们来重温下学校时代就学过的哈希算法吧。我
- Kotlin 支持泛型, 语法和 Java 类似。例如,泛型类:class Hello<T>(val value: T)val
- 先执行以一个简单的示例:static void Main(string[] args) { &nb
- 工厂模式在Java应用程序中对象无处不在,这些对象都需要进行创建,如果创建的时候直接new对象,那么如果我们要更换对象,所有new对象的地方
- 自定义log4j日志文件命名规则项目中的日志需要采用一致的命名规范和文件规范,命名规则为:项目模块标识_index_日期时间_日志级别.lo
- 前言我们开始 Flutter 动画相关篇章之旅,在应用中通过动效能够给用户带来更愉悦的体验,比较典型的例子就是一些直播平台的动效了,比如送火
- 1、效果展示2、布局文件<?xml version="1.0" encoding="utf-8"
- 目录1、通过session中的token验证步骤1:创建自定义注解步骤2:创建自定义 * (@slf4j是lombok的注解)步骤3:将自定
- 本文实例通过前面学过的Paint、Canvas等2D绘画技术来实现在手机屏幕上绘制Android机器人。具体代码实现和效果:用来显示自定义的
- 本文将引导您完成 2 个示例,演示如何在 Flutter 中获取设备标识符使用 platform_device_id如果您只需要运行应用程序
- 随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁。很多小伙伴对于分布式锁还不是特别了解,所以特地总结了一篇文章,让大家一文读懂分
- 一、this关键字this是一个引用,它指向自身的这个对象。看内存分析图:假设我们在堆内存new了一个对象,在这个对象里面你想象着他有一个引
- 背景描述公司小程序商城项目,服务器为阿里云。前段时间总是出现服务器CPU报警现象(设置的阈值为95%,CPU使用率大于95%会自动报警)。通
- 创建SpringBoot项目,启动后,默认的访问路径即主机IP+默认端口号8080:http://localhost:8080/此时,我们就