一个小栗子聊聊JAVA泛型基础
背景
周五本该是愉快的,可是今天花了一个早上查问题,为什么要花一个早上?我把原因总结为两点:
- 日志信息严重丢失,茫茫代码毫无头绪。
- 对泛型的认识不够,导致代码出现了BUG。
第一个原因可以通过以后编码谨慎的打日志来解决,我们今天主要来一起回顾下JAVA泛型基础。
一个小栗子
先看下面一个例子,test1实例化一个List容器的时候没有指定泛型参数,那么我们可以往这个容器里面放入任何类型的对象,这样是不是很爽?但是当我们从容器中取出容器中的对象的时候我们必须小心翼翼,因为容器中的对象具有运行时的类型信息,这意味着你不能够将一个带有运行时类型信息的对象赋值给另一个类型,否则ClassCastException。
@Test public void test1() throws Exception {List list = new ArrayList();list.add("float.lu");list.add(1);String name = (String) list.get(0); int num = (Integer) list.get(1); System.out.println(String.format("name[%s], num[%s]", name, num)); } |
上面的代码没问题,可以很好地编译和运行通过,问题是我必须要事先很清楚地知道容器中的索引为0的对象是什么类型,索引为1的对象是什么类型,很显然,这在实际应用中是不切实际的,也是一种很不靠谱的做法,那么这个问题如何解决呢?泛型。
引入泛型
为了解决这个问题,我们引入泛型,下面代码可以看出与上面不同的是我们在实例化容器的时候加了<String>这个东西,这个东西的学名叫做泛型参数,就像普通方法带有参数一样,interface List<E>中的E为形式参数、而String为实参。
|
引入泛型后,我们规定这个容器中只能存放类型为字符串类型的对象,好的,编译器可以识别泛型并帮我们检查编译错误,上面的代码中1处会出现编译错误。注意:泛型信息仅仅存在于编译期间,编译器可以通过泛型信息来对代码是否存在违规行为(编译错误)来进行检查,当编译器将代码编译为字节码之后,泛型信息将不复存在,然而对象的运行时信息仍然是有的,这就解释了为什么会出现ClassCastException。
别高兴太早
有了泛型我们可以让代码安全地通过编译,并且我们认为他是安全的了,嘿嘿,是否就真的安全了呢?是否就能和ClassCastException说拜拜了呢?答案是:NO。看看下面这段代码:
|
上面这段代码编译没有问题,我们没有直接将泛型参数为String的容器赋值给泛型参数为Integer的容器,而是花了点点小心思,我们现将list赋值给_list,_list生命为可以存储任何类型,也就相当于无特定类型,而后我们又把_list赋值给integerList容器,integerList容器被声明为只能存储类型为Integer的对象。悲催的是这段代码在运行的时候报了ClassCastException,很明显,我们知道在迭代integerList容器中的对象的时候,这些对象是有运行时类型信息的,当带有String类型信息的对象赋值给Integer的时候显然就报错了。这一切看起来似乎没问题,符合逻辑,但是有一个问题我们还没有问:为什么会没有编译错误?
泛型术语
在学习数学的时候我们往往会对一个证明题进行论证,而论证之前我们手上往往会有一些不需要证明的已知定理,下面这些“定理”将被用来直接回答上一节中遗留的问题。
- List<E>被称作泛型类型。
- List<E>中的E被称为类型变量或类型参数。
- List<String>被称为参数化类型。
- List<String>中的String被称为实际类型参数。
- List<E>中的<>年typeof。
- List被称为原始类型。
- 参数化类型可以引用一个原始类型对象,编译报告警告。
- 原始类型可以引用一个参数化类型对象,编译报告警告。
由上可知,List<Integer> integerList = _list;可以通过编译。
看清本质
经过上面的一些小波折,我们了解一些关于泛型的本质:泛型是给javac编译器使用的,javac是JAVA的编译器,而泛型可以让代码在编译期间确定类型安全,比如我们告诉编译器某个容器只能存储某种类型的对象,那么编译器会为我们好好地检查,确保类型安全,但是安全是相对的,只要我们逃过编译器,我们就有一百种方法让代码ClassCastException(比如反射)。同时编译之后参数化类型在运行时没有任何泛型信息,也就是为什么List.class和List<String>.class是同一个东西。除了参数化类型之外,容器中的对象在运行的时候是有类型信息的,也就是为什么会ClassCastExcetion。关于泛型还有很多内容,这里不做多讲,文中有误也欢迎留言讨论。
转载于:https://www.cnblogs.com/tv151579/p/7582288.html
一个小栗子聊聊JAVA泛型基础相关推荐
- java泛型 简书_一文带你认识Java泛型基础
Java泛型基础 1. 认识泛型 泛型是在JDK1.5之后增加的新功能. 泛型可以解决数据的安全性问题, 主要的原理是在类声明的时候通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型. ...
- java 获取泛型_聊聊Java泛型擦除那些事
>版权申明]非商业目的注明出处可自由转载 博文地址:https://blog.csdn.net/ShuSheng0007/article/details/89789849 出自:shushen ...
- c语言 lookup函数怎么用_菜鸟记502用lookup和vlookup函数核对数据的一个小栗子
欢迎转发扩散点在看 万一您身边的朋友用得着呢? 各位朋友早上好,小菜继续和您分享经验之谈,截止今日小菜已分享400+篇经验之谈,可以文章编号或关键词进行搜索. 微信推送规则发生改变,如果您想看到小菜每 ...
- unity做一个小游戏(适合零基础或者巩固加深unity中的工具类的用法)
今天跟着官方unity做了一个小游戏.巩固一下之前学习的unity的知识.注意unity的版本要在2018.3以上 大概游戏是这样子的如图:人物只能控制左右移动,空格发射饼干,动物从屏幕上方随机出现在 ...
- java反射泛型类型,【Java反射】Java 泛型基础
Java Reflect 综述 方法的反射 成员变量的反射 构造函数的反射 类加载机制 在面向对象的世界里,万事万物皆对象. 但在Java里面有两样东西不是对象:静态的成员.普通数据类型类(但它们有封 ...
- 从一个小故事聊聊字符编码那些事
联通不如移动的故事 在编码界一直流传着联通不如移动的一个故事... 请不要误会,联通和移动和本篇文章所说的编码确实没什么关系,但请出联通和移动帮忙做个小实验,再来仔细说说编码. 在Windows系统下 ...
- 一个小例子体会Java反射的动态性
背景:需要在程序运行时或者说某段代码运行后才能知道要创建哪个类的对象. import java.util.Random;/*** @Author: Yeman* @Date: 2021-10-02-2 ...
- java操作excel_每天一个小技术之Java操作Excel
/*** @Auther: Mr.BoBo* @Date: 2020/6/10 15:38* @Description:*/ public class ExcelUtil { private fina ...
- Java基础系列二:Java泛型
该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 一.泛型概述 1.定 ...
最新文章
- 单片机编程好学吗?单片机初学者怎样看懂代码?
- synchronsized修饰方法的使用
- java将clob类型文件写到磁盘_Java对Oracle中Clob类型数据的读取和写入
- 网络投票轻松实现自动化 - 验证码识别的基本思路及方法
- Python中单线程、多线程与多进程的效率对比实验
- J2EE搭建Dynamic web SpringMVC工程404错误分析(一)
- 格式说明_ISO11784/85 FDX-B动物芯片格式写码说明
- java枚举类中字段有没有必要加final____枚举类字段 Field ‘xxx‘ may be ‘final‘
- Java多线程基础学习一:线程的6种状态和相互转化
- 黑客恶意修改化学成分参数,远程投毒饮用水
- 清除浮动(HTML、CSS)
- (转)开源的大文件上传组件NeatUpload
- 计算机网络速度慢原因,导致电脑网速变慢的七大原因
- 10个免费商用的图片网站分享
- html剧场座位设计图,报告厅舞台到第一排的距离多少合适 剧院主舞台离座位最佳距离尺寸设计图...
- 免费通信时代何时真正到来?
- C语言————exec函数族
- vue js 复制div区域内容
- uCOS3源码解析视频教程-第4季第7部分-朱有鹏-专题视频课程
- 新手摸爬滚打:vue+springboot前后端分离项目演示(三)——axios实现前后端交互