JAVA基础_泛型

什么是泛型


泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉”类型”信息,是程序的运行效率不受影响,对于参数化的泛型类型,getClass()方法返回值和原始类型完全一样。由于编译生成的字节码会擦除泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,然后再调用add()方法即可


GenericDemo.java

public class GenericDemo {public static void main(String[] args) {// 未使用泛型,则可以添加任意Object类型的数据List noGrnerics = new ArrayList<>();noGrnerics.add(1);noGrnerics.add("hello");noGrnerics.add("1L");noGrnerics.add(new GenericDomain(1L,"Generic"));// 由于没有使用泛型,在取出数据时必须要知道某个位置上的某个数据的数据类型,并加以强制转换,否则要出错,除非用Object接收。Integer integer = (Integer) noGrnerics.get(0);System.out.println("integer = " + integer);// 由于不知道某个位置上的数据类型,用Object接收Object objIndex1 = noGrnerics.get(1);System.out.println("objIndex1 = " + objIndex1);Object objeIndex3 = noGrnerics.get(3);System.out.println("objeIndex3 = " + objeIndex3);// 虽然可以通过类对象来知道类属性,但是这样不是太麻烦了吗??System.out.println("objeIndex3.getClass() = " + objeIndex3.getClass());// 使用泛型List<String> strs = new ArrayList<>();strs.add("str1");strs.add("str2");strs.add("str3");// 因为指定了这个List中只能放置String类型的数据,当这里放置其他类型的数据时就会报错,因为不能装进去// 从某种角度上可以认为泛型解决了强制类型转换,使数据特征更明显,拥有一致性
//        strs.add(1);String str = strs.get(0);System.out.println("str = " + str);}}

绕过编译时泛型,添加非泛型类型数据:GenericDemo2.java

public class GenericDemo2 {/*** 程序目标,向一个List<String>的泛型数组中添加Integer类型的数据* * @param args*/public static void main(String[] args) {List<String> strs = new ArrayList<>();strs.add("str1");strs.add("str2");strs.add("str3");strs.add("str4");// 这里是添加不进去的,因为指定了泛型类型,且没有泛型擦除// strs.add(new Integer(1));System.out.println("Before add a Integer value : " + strs);// 通过泛型在运行时擦除的原理,利用反射向泛型中添加Integer数据Class<List<String>> clazz = (Class<List<String>>) strs.getClass();try {// 这里在利用反射获取add方法时,如果参数类型指定为String.class,// 则说明add方法为,java.util.ArrayList.add(java.lang.String)// 而我们传入了一个Integer类型的数据,则显然不能添加成功,会抛出 java.lang.NoSuchMethodExceptionclazz.getDeclaredMethod("add", String.class).invoke(strs, new Integer(1));// 这里原因一样,java.util.ArrayList.add(java.lang.Integer) 但是用的int,// 请记住,java是强类型语言,这里不存在自动装箱和拆箱clazz.getDeclaredMethod("add", Integer.class).invoke(strs, 2);// 这里也是不正确的,因为Class<List<String>>指定了放Stringclazz.getDeclaredMethod("add", Integer.class).invoke(strs, new Integer(4));//同上clazz.getDeclaredMethod("add", int.class).invoke(strs, 5);} catch (Exception e) {e.printStackTrace();} finally {//正确做法try {clazz.getDeclaredMethod("add", Object.class).invoke(strs, 3);System.out.println("strs = " + strs);// 只有Object能行clazz.getDeclaredMethod("add", String.class).invoke(strs, "4");System.out.println("strs = " + strs);} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException| NoSuchMethodException | SecurityException e) {// TODO Auto-generated catch block
                e.printStackTrace();}}System.out.println("After add a Integer value : " + strs);}}

解释为什么只能用Object,运行时会擦除泛型,下面的代码清单就可以验证

public class GenericTypeDemo {public static void main(String[] args) {// 这里的字节码类型为ArrayListList<String> strings = new ArrayList<>();// 这里的字节码类型也为ArrayListList<Integer> integers = new ArrayList<>();System.out.println("strings.getClass() = " + strings.getClass());System.out.println("integers.getClass() = " + integers.getClass());System.out.println("integers.getClass() == strings.getClass() = " + (integers.getClass() == strings.getClass()));}}


泛型中的?通配符

  • 需求:定义一个方法,该方法用于打印出任意参数类型化的集合中的所有数据。


public class GenericDemo3 {public static void main(String[] args) {// 需求:定义一个方法,该方法用于打印出任意参数类型化的集合中的所有数据。List<String> strings = new ArrayList<>();strings.add("a");strings.add("b");strings.add("c");strings.add("f");        printCollectionElements(strings);printStringCollectionElements(strings);List<Integer> integers = new ArrayList<>();integers.add(1);integers.add(2);integers.add(3);integers.add(4);printCollectionElements(integers);// 这里就不能用了
//        printStringCollectionElements(integers);
        }/*** 定义一个方法,该方法用于打印出任意参数类型化的集合中的所有数据。* 这种是通配方法,能够打印所有的,其通配之处就在与?,?可以引用其他各种参数化的类型* @param collection*/public static void printCollectionElements(Collection<?> collection) {collection.forEach(System.out::println);}/*** 打印String类型的集合数据,由于制定了泛型类型为String,则只能打印String类型的集合* @param collection*/public static void printStringCollectionElements(Collection<String> collection) {collection.forEach(System.out::println);}}


  • 总结

使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,如size(),不能调用与参数化有关的方法,如add(E e)


泛型中?的扩展

  • 限定通配符的上边界
    • 正确 List<? extends Number> x = new ArrayList<Integer>();
    • 错误 List<? extends Number> x = new ArrayList<String>();
  • 限定通配符的下边界
    • 正确 Vector<? super Integer> x = new Vector<Number>();
    • 错误 Vector<? super Integer> x = new Vector<Byte>();
  • 总结
    • 限定通配符总是包括自己

转载于:https://www.cnblogs.com/homeword/p/7497121.html

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

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

相关文章

python!!!!惊了,这世上居然还有这么神奇的东西存在

第一次接触到python的时候实在看学习3Blue1Brown的视频线性代数的本质的时候。惊奇的是里面的视频操作&#xff0c;例如向量的变化&#xff0c;线性变换等都是由python用代码打出来的。那时的我只是以为python是类似matlab类型的数学软件。人工智能&#xff0c;大数据的兴起&am…

int定义源码 python_python学习(第一章)

1.print输出语句# 输出字符串 print(hello) # 输出数字 print(234) print("I come from China") print("I come from China") # 输出表达式 print(71) # 将数据输出到文件中 file fp open(D:/pythoncode.txt, a) print("I come from China",…

使用Specs2和客户端API 2.0进行富有表现力的JAX-RS集成测试

毫无疑问&#xff0c; JAX-RS是一项杰出的技术。 即将发布的规范JAX-RS 2.0带来了更多的强大功能&#xff0c;尤其是在客户端API方面。 今天的帖子的主题是JAX-RS服务的集成测试。 有很多出色的测试框架&#xff0c;例如REST可以确保提供帮助&#xff0c;但是我要展示的方式是使…

android设置控件形状,Android控件自定义形状

Android中处理控件的各种形状可以用到Shape&#xff0c;ApiDemos中有相关的例子&#xff0c;在com.example.android.apis.graphics中的ShapeDrawable1类中有很详细的介绍和例子。使用xml的方法也能达到同样的效果&#xff0c;而且更加方便。如下面的代码所示&#xff1a;XML/HT…

赋值

非阻塞赋值产生寄存器&#xff0c;a<b,b<c. a的值传给c需要两个时钟&#xff0c;两条语句同时执行。阻塞赋值ab&#xff0c;bc&#xff0c;两条语句顺序执行&#xff0c;不产生寄存器。 小明教ic4转载于:https://www.cnblogs.com/xiaoxuesheng993/p/7503893.html

python web开发-flask访问请求数据request

Request对象在web应用的开发中是一个非常重要的对象&#xff0c;主要用来获取用户发来的请求数据。 常用属性参考&#xff1a;http://docs.jinkan.org/docs/flask/api.html#flask.request 下面我们以一个表单提交的例子来说明一些常用request属性的使用。 创建一个表单的templa…

ActiveMQ群集,持久订阅者和虚拟主题可助您一臂之力

因此&#xff0c;您希望跨分布式主题使用ActiveMQ进行发布-订阅&#xff0c;并且要可靠。 您可以只使用永久订阅&#xff0c;对不对&#xff1f; 可以&#xff0c;但是&#xff0c;如果将群集与ActiveMQ一起使用&#xff0c;则可能会遇到意外行为。 我最近在一个客户端上&#…

android 对称加密和非对称加密,Android开发加密之对称与非对称加密算法使用案例.pdf...

Android开发加密之对称与非对称加密算法使用案例消息摘要md5&#xff1a;登录注册&#xff0c; sha1对称加密 1.des:Data Encryption Standard&#xff0c;数据加密标准 2.aes&#xff1a;Advanced Encryption Standard &#xff0c;更高级的方式对称加密特点&#xff1a;加…

unity 半透明混合问题_Unity 实时 半透明 阴影 shader

简单阴影制作思路&#xff1a;1&#xff1a;在角色脚底 放置一块平板2&#xff1a;shader中 根据平板传入的矩阵 以及 光照 对角色进行变换3&#xff1a; 得到投影在地面上的阴影4&#xff1a;阴影直接渲染到 屏幕上缺点&#xff1a;上面的阴影无法 增加半透明阴影效果&#xf…

Showplan 逻辑运算符和物理运算符参考

本文档已存档&#xff0c;并且将不进行维护。运算符说明了 SQL Server 如何执行查询或数据操作语言 (DML) 语句。 查询优化器使用运算符生成查询计划&#xff0c;以创建在查询中指定的结果或执行在 DML 语句中指定的操作。 查询计划是由物理运算符组成的一个树。 您可以使用 SE…

在win10中通过Anaconda3安装tensorflow

安装Anaconda3&#xff0c;然后在所有程序中启动“Anaconda Navigator”&#xff0c;如图&#xff1a; 切换到“Enviroments"(环境)中&#xff0c;在右边有个显示环境的列表&#xff0c;默认有"base(root)"&#xff0c;然后单击底部的”Create"按钮创建一个…

ddr5内存上市时间_DDR5内存明年才能上市,SK Hynix已预研DDR6:12Gbps

拼 命 加 载 中 ... 随着去年Q4季度DRAM芯片价格开始下跌,DDR4内存的价格已经有了松动,很多人还期待着8GB内存降回200多元的价格呢。现在的DDR4内存已经有了继任者——DDR5,标准及芯片生产都完成了,不过尚无平台支持,最快今年底才会有DDR5内存上市,更多地还是2020年上市。…

功能接口简介–在Java 8中重新创建的概念

世界各地的所有Java开发人员都将至少使用以下接口之一&#xff1a;java.lang.Runnable&#xff0c;java.awt.event.ActionListener&#xff0c;java.util.Comparator&#xff0c;java.util.concurrent.Callable。 声明的接口之间有一些共同的特征&#xff0c;该特征是它们在接口…

计算机专业职业规划范文800字,计算机专业学生职业生涯规划书

作为一名计算机学生&#xff0c;这门专业比较难学&#xff0c;所以在进入大学后&#xff0c;我必须得为自己做一份职业生涯规划&#xff0c;让自己在大学几年里能完成学业&#xff0c;成功的奔赴社会工作。一、自我分析我虽然是自己选的计算机专业&#xff0c;但是兴趣并不是很…

Python核心模块——urllib模块

urllib模块中的方法 1.urllib.urlopen(url[,data[,proxies]]) 打开一个url的方法&#xff0c;返回一个文件对象&#xff0c;然后可以进行类似文件对象的操作。本例试着打开google >>> import urllib >>> f urllib.urlopen(http://www.google.com.hk/) >&…

HTML 中点击a标签,页面跳转执行过程

HTML链接使用的是<a>标签点击超链接,后台的执行大致如下:<a href"https://www.baidu.com">超链接</a>根据链接地址看出,执行的是https协议点击超链接,首先在本地的hosts文件(C:\Windows\System32\drivers\etc\hosts)中查找是否有与网址匹配的ip如果…

JS中原型与原型链

一. 普通对象与函数对象 JavaScript 中&#xff0c;万物皆对象&#xff01;但对象也是有区别的。分为普通对象和函数对象&#xff0c;Object 、Function等 是 JS 自带的函数对象。下面举例说明。 var o1 {}; var o2 new Object(); var o3 new f1();function f1(){}; var f2…

计算机专业学生求职信500字,计算机专业求职信500字范文

计算机专业求职信500字范文尊敬的领导&#xff1a;您好&#xff01;请恕打扰&#xff0c;我是荆楚理工学院计算机工程学院的一个大学生&#xff0c;即将面临毕业.我很荣幸有机回向您呈上我的个人资料.在投身社会之际,为了找到符合自己专业和兴趣的工作,更好地发挥自己的才能,实…

一年中所有节日的排列顺序_计数问题(二)-排列组合的使用

在计数问题(一)中我们分析了排列和组合的定义&#xff0c;计算方法以及公式的含义。排列组合的基本定义讲述的是从一列元素中分先后&#xff08;排列&#xff09;或不分先后地选出部分元素&#xff0c;其可能的选择方法数。在这一期中我们会更仔细地分析组合的公式的含义&#…

使用Spring数据和Thymeleaf实现Bootstrap分页

Twitter Bootstrap具有非常好的分页UI &#xff0c;在这里我将向您展示如何使用Spring Data Web分页功能和Thymeleaf条件评估功能来实现它。 引导程序中的标准分页 受Rdio启发的简单分页&#xff0c;非常适合应用程序和搜索结果。 大块很难错过&#xff0c;易于扩展&#xff0…