这里想说一下在集合框架前需要理解的小知识点,也是个人的肤浅理解,不知道理解的正不正确,请大家多多指教。
这里必须谈一下java的泛型,因为它们联系紧密,我们先看一下这几行代码:

Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println( c1 + "==" + c2 + " is " + (c1 == c2) );

  

这里主要想测试一下这两个类是不是相等的,根据我之前的认识,这应该是不相等的,但是运行输出的结果是:

class java.util.ArrayList==class java.util.ArrayList is true

根据打印结果显然c1 和 c2都叫class java.util.ArrayList ,所以后面是否相等跟的是 true,居然和我的预期完全相反的,
这是怎么回事呢,这就要提到java泛型里的类型擦除(type erasue),这黑科技的提出肯定是有多方面原因的,我摘录了一些我了解到的原因。
让我们一步步了解:

一、保持代码版本的兼容性
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的"任意化","任意化"带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。所以后期引入了泛型,泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。但是需要保持代码的兼容性

二、目前了解到通常情况下编译器处理泛型有两种方式,java选择了类型擦除,两种方式如下:
1.Code specialization。在实例化一个泛型类或泛型方法时都产生一份新的目标代码(字节码or二进制代码)。例如,针对一个泛型list,可能需要 针对string,integer,float产生三份目标代码。
2.Code sharing。对每个泛型类只生成唯一的一份目标代码;该泛型类的所有实例都映射到这份目标代码上,在需要的时候执行类型检查和类型转换。
C++中的模板(template)是典型的Code specialization实现。C++编译器会为每一个泛型类实例生成一份执行代码。执行代码中integer list和string list是两种不同的类型。这样会导致代码膨胀(code bloat),
Code specialization另外一个弊端是在引用类型系统中,浪费空间,因为引用类型集合中元素本质上都是一个指针。没必要为每个类型都产生一份执行代码。而这也是Java编译器中采用Code sharing方式处理泛型的主要原因。
Java编译器通过Code sharing方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。将多种泛型类形实例映射到唯一的字节码表示是通过类型擦除(type erasue)实现的。

类型擦除的来世大概说了,我们看看类型擦除大概是怎么回事:
我们都知道重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义,根据java编辑器处理泛型的方式,上面代码编译完成后应该会变成这样:

Class c1 = new ArrayList<Object>().getClass();
Class c2 = new ArrayList<Object>().getClass();
System.out.println( c1 + "==" + c2 + " is " + (c1 == c2) );

  

可以看出来,无论类是什么,经过编译器后再虚拟机里运行都是相同的类,所以结果是相等的。

所以总结一下类型擦除引起一些奇怪的现象,包括:

  • 泛型类并没有自己独有的Class类对象。比如上面测试的例子。
  • 静态变量是被泛型类的所有实例所共享的。比如声明为MyClass<T>的类,不管是通过new MyClass<String>还是new MyClass<Integer>创建的对象,都是共享一个静态变量。
  • 泛型的类型参数不能用在Java异常处理的catch语句中。因为异常处理是由JVM在运行时刻来进行的。由于类型信息被擦除,JVM是无法区分两个异常类型MyException<String>和MyException<Integer>的。对于JVM来说,它们都是 MyException类型的。也就无法执行与异常对应的catch语句。

java之集合类框架的简要知识点:泛型的类型擦除的更多相关文章

  1. Java泛型:类型擦除

    类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...

  2. Java泛型之类型擦除

    类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦): ...

  3. 泛型的类型擦除后,fastjson反序列化时如何还原?

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra~ 在前面的文章中,我们讲过Java中泛型的类型擦除,不过有小伙伴在后台留言提出了一个问题,带有泛型的实体的反序列化 ...

  4. JAVA 泛型之类型擦除

    ★ 泛型是 JDK 1.5 版本引进的概念,之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容. CollectionTest.java ---编译成CollectionTest. ...

  5. Java泛型-类型擦除

    一.概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变 ...

  6. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  7. 转:有关Java泛型的类型擦除(type erasing)

    转载自:拈花微笑 自从Java 5引入泛型之后,Java与C++对于泛型不同的实现的优劣便一直是饭后的谈资.在我之前的很多training中,当讲到Java泛型时总是会和C++的实现比较,一般得出的结 ...

  8. java 泛型的类型擦除与桥方法

    泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...

  9. java 泛型的类型擦除和桥方法

    oracle原文地址:https://docs.oracle.com/javase/tutorial/java/generics/erasure.html 在Java中,泛型的引入是为了在编译时提供强 ...

随机推荐

  1. Qss样式(二)

    Qss 其实就是一段文本,当然得按一定格式来写.下面请看Qss的语法格式: 选择器 { 属性1:值:属性2:值:--属性n:值:} 对应上篇文章的Qss样式: 现在我们可以来解释这段话的意思了: 对应 ...

  2. 【Lucene4.8教程之五】Luke

    一.Luke基本内容 1.Luke简介 Luke可用于查看Lucene创建的索引,并对其进行基本操作. 2.创建Luke (1)从Github上下载源文件 https://github.com/tar ...

  3. WordPress插件制作教程(一): 如何创建一个插件

    上一篇还是按照之前的教程流程,写了一篇WordPress插件制作教程概述,从这一篇开始就为大家具体讲解WordPress插件制作的内容.这一篇主要说一下插件的创建方法. 相信大家都知道插件的安装文件在 ...

  4. MVC4商城项目四:应用Bundle捆绑压缩技术

    从MVC4开始,我们就发现,项目中对Global.asax进行了优化,将原来在MVC3中使用的代码移到了[App_Start]文件夹下,而Global.asax只负责初始化.其中的BundleConf ...

  5. Jmeter的简单练习

    一.安装Jmeter 1.下载Jmeter 下载地址:http://jmeter.apache.org/download_jmeter.cgi 目前最新版为2.9,其余文件如源代码等也可从如下官网下载 ...

  6. SQLServer优化资料整理(一)

    查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...

  7. 哥德尔,图灵和康托尔 part 1 哥德尔编号

    在看计算理论相关的书的时候,偶然看到这个blog,http://skibinsky.com/godel-turing-and-cantor-the-math/,写的很好.我觉得用自动机的方式讲计算理论 ...

  8. OpenStack Keystone v3 API新特性

    原连接 http://blog.chinaunix.net/uid-21335514-id-3497996.html keystone的v3 API与v2.0相比有很大的不同,从API的请求格式到re ...

  9. unity3d 捕获系统日志,来处理一些问题

    注册系统日志回调,根据日志内容和类型处理一些特殊问题 using UnityEngine; using System.Collections; public class SetupVerificati ...

  10. 苹果试图做?XCode6 放弃prefix.pch档

    当我们升级到XCode6后, 新建project发现默认是没有pch文件的.非常多人開始不习惯了,苹果到底为什么要取消这一个pch文件. 苹果觉得,因为组件单一模块的原因.你不应该在你的prefix代 ...