java 泛型学习随笔
对于java 泛型 编译时处理,运行时擦除的特点理解
- 对于编译时处理
- 在使用泛型相关的类或方法时,如果声明时的类型和具体使用时的类型不一致则直接会编译不通过
- 对于运行时擦除
- 当在运行时对两个相同类型但泛型的具体类型不同时,在运行时实际都是操作的相同的类型,而不会体现出来泛型的的具体类型;
public static void main(String[] args){ List a = Collections.emptyList();
List b = Collections.emptyList();
// true , 对于不包含泛型初始化的list实际都是使用的相同的实例数据
LOGGER.info(String.valueOf(a == b)); List<String> a1 = Collections.emptyList();
boolean v = a == a1;
// true, 对于 a 和 a1 两个参数的类型实际是不同的,但在运行时实际是对于a和a1的类型实际都是相同的List类型; 可以通过 javap -v 类名 来查看编译后的class文件
LOGGER.info(String.valueOf(v)); List<Integer> b1 = Collections.emptyList();
// 由于a1和b1的泛型的具体类型不一致,因此在编译时不会通过
// boolean v1 = a1 == b1
}
对于泛型的显式限定和隐式限定区别
public static void castQuestion() {
// 在执行实例化操作时,实际已经隐式限定了当前对象的类型
// 在执行具体操作时,虽然根据变量的限定符显式定义,但在实际使用中就会抛出错误
Container<StringBuilder> stringContainer = new Container("1");
StringBuilder element = stringContainer.getElement(); } // 自定义内部容器类,类型为泛型
// 单界限操作: E extends CharSequence,这里限定了泛型的类型只能为CharSequence的子级
public static class Container<E extends Serializable> {
private E element; public Container(E element) {
this.element = element;
// 可以看到当前元素的实际类型
System.out.println(element.getClass().getTypeName());
} // 方法
public E getElement() {
return element;
} public void setElement(E element) {
this.element = element;
}
}
可以看到在指定 new 时未显式指定对象元素类型,但通过调用有参构造方法实际已限定了当前对象的element元素类型;
虽然对象变量显式限定了当前变量的泛型,对于操作方法实际是根据调用者的具体泛型类型进行限制,因此可以看到 "StringBuilder element = stringContainer.getElement();" 返回值类型为 StringBuilder;
而由于对象中的实际类型为String类型,当将String类型强制赋值为Integer类型数据时,就会抛出ClassCastException
由于泛型存在编译时校验,运行时擦写的特点,因此为了保证运行时也提供泛型类型校验, 在Collections中提供了 checked*的工具类,在执行操作时保证了运行时的类型校验
public void collectionGenericType() {
List<Integer> integers = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
// 由于泛型存在编译时校验,运行时擦写
List noGenericTypeList = integers;
System.out.println(noGenericTypeList == integers);
// 虽然 noGenericTypeList 引用了 integers
// 运行时泛型擦写 List<Integer> -> List<Object> -> List
// 因此可以写入任意类型的数据
noGenericTypeList.add("A");
// 由于数据读取时需要进行类型转换(转换为泛型的指定类型)因此会抛出ClassCastException
// integers.forEach(System.out::println);
// 而对于noGenericTypeList由于没有泛型的约束,因此读取数据是都是按照Object类型处理
noGenericTypeList.forEach(System.out::println);
// 在转换时并没有执行类型检查因此支持直接转换
List<Integer> castList = new ArrayList<>(noGenericTypeList);
// 因此为了避免类型擦写导致的异常,因此需要使用包装类型工具类
// 当转换为checkedList时并不会进行类型校验
/**
* Wrapper(装饰器)模式的使用
* Collections.checked*接口弥补了 泛型运行时擦写的不足
* 强类型: 编译时泛型强制类型检查,运行时利用Collections.checked*强类型检查
*/
List<Integer> checkedList = Collections.checkedList(castList, Integer.TYPE);
// 会生成新的数据
System.out.println(checkedList == castList); noGenericTypeList = checkedList;
// 对于checkedList在执行添加时,会执行类型校验,因此会直接抛出错误
noGenericTypeList.add("B");
}
java 泛型学习随笔的更多相关文章
- Java泛型学习笔记 - (七)浅析泛型中通配符的使用
一.基本概念:在学习Java泛型的过程中, 通配符是较难理解的一部分. 主要有以下三类:1. 无边界的通配符(Unbounded Wildcards), 就是<?>, 比如List< ...
- Java泛型学习笔记--Java泛型和C#泛型比较学习(一)
总结Java的泛型前,先简单的介绍下C#的泛型,通过对比,比较学习Java泛型的目的和设计意图.C#泛型是C#语言2.0和通用语言运行时(CLR)同时支持的一个特性(这一点是导致C#泛型和Java泛型 ...
- java泛型学习(2)
一:深入泛型使用.主要是父类和子类存在泛型的demo /** * 父类为泛型类 * @author 尚晓飞 * @date 2014-7-15 下午7:31:25 * * * 父类和子类的泛型. * ...
- Java泛型学习---第二篇
泛型学习第一篇 1.泛型之擦拭法 泛型是一种类似"模板代码"的技术,不同语言的泛型实现方式不一定相同. Java语言的泛型实现方式是擦拭法(Type Erasure). 所谓擦拭法 ...
- java泛型学习(1)
java泛型(Generices Type) --->概念:泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和 ...
- Java泛型学习一
Java泛型 所谓泛型,就是变量类型的参数化.泛型是java1.5中引入的一个重要特征,通过引入泛型,可以使编译时类型安全,运行时更少抛出ClassCastException的可能.一提到参数化,最熟 ...
- Java 泛型学习总结
前言 Java 5 添加了泛型,提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,可以为以前处理通用对象的类和方法,指定具体的对象类型.听起来有点抽象, ...
- Java泛型学习笔记 - (六)泛型的继承
在学习继承的时候, 我们已经知道可以将一个子类的对象赋值给其父类的对象, 也就是父类引用指向子类对象, 如: Object obj = new Integer(10); 这其实就是面向对象编程中的is ...
- java 泛型学习
http://blog.csdn.net/archie2010/article/details/6232228 学习集合框架的时候经常用hasmap<Integer,Integer>就是泛 ...
随机推荐
- centos iso镜像自动挂载
vim /etc/fstab 添加如下行:/usr/ison/centos.iso /media/cdrom iso9660 defaults,loop 0 0
- 企业级Registry仓库Harbor的部署与简介
Harbor 是Vmware公司开源的企业级Docker Registry管理项目,开源项目地址:https://github.com/vmware/harbor Harbor的所有组件都在Docke ...
- 并发编程(叁):synchronize
synchronize synchronized是Java中的关键字,是一种常用的线程同步锁. 用法 注意:在理解synchronized时,要知道一个核心点,synchronized锁定的不是代码, ...
- 安卓手机没有twrp的情况,如何下刷入magisk并获得root权限.
安装adb工具 https://dl.google.com/android/repository/platform-tools_r29.0.6-windows.zip 从以上地址下载,然后解压到任意目 ...
- Soft-to-Hard Vector Quantization for End-to-End Learning Compressible Representations
郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! Abstract: 我们提出了一种新的方法,通过端到端的训练策略来学习深度架构中的可压缩表征.我们的方法是基于量化和熵的软(连续)松弛,我 ...
- Tmux安装和使用
1.What's tmux tmux 是一个终端复用器: 可以激活多个终端或窗口, 在每个终端都可以单独访问,每一个终端都可以访问,运行和控制各自的程序.tmux类似于screen,可以关闭窗口将程序 ...
- 扫盲--CRM系统和ERP系统的区别
企业规模在逐步扩大的时候,为了提高生产和管理的效率,经常需要用到相关管理软件.很多企业管理者在选择管理软件的时候犯了难,面对CRM系统和ERP系统不知如何选择无法下手.那么,CRM和ERP的区别是什么 ...
- JavaScript作用域与对象
1 - 作用域 1.1 作用域概述 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域.作用域的使用提高了程序逻辑的局部性,增强了程序的可靠 ...
- 要不是真的喜欢学技术,谁会来用Python爬小姐姐啊
养成习惯,先赞后看!!!不用于任何商业价值,只是自己娱乐.否则 爬虫爬的好,牢饭吃到饱.这是我们这次爬取的网址:https://www.vmgirls.com/ 很多人学习python,不知道从何学起 ...
- 初学WebGL引擎-BabylonJS:第4篇-灯光动画与丛林场景
前几章接触的案例都是接近静态的,由这张开始开始接触大量动态的内容,包括 球体灯光,变动的形体,以及一个虚拟的丛林场景 下章我会试着结合1-9案例的内容做出一个demo出来 [playground]-l ...