今晚抽空看了下周老大著作《深入理解Java虚拟机:JVM高级特性与最佳实践》 里其中的一篇文章,关于Java泛型与类型擦除的解析,受益匪浅,在此也做一点笔记以诸分享~

 

众所周知,Java的泛型是JDK1.5版本之后才有的特性,在没泛型特性之前,只能通过Object是所有类的父类和类型强制转换来实现类型泛化,那个时候,只有依靠程序员与运行期的虚拟机了解你即将要转化的是什么类型,为啥,一是代码你码的,二来还不是因为Object皆所有类的father,而众多方法返回的类型又是Object,那么基于这些,较容易引起当程序员不小心来个失误,强制转换错相关类型引起ClassCastException的运行时异常【注:工作中,曾经就检查发现一程序员编写的代码出现这种失误而引起程序直接类型强制转换抛了个异常,多悲催啊是不-_-|】

 

泛型在多种语言也都有所应用:Java、C# 等,而C#的泛型使用与Java虽大致相同,但本质却不同。

C#乃类型膨胀(真实泛型),无论在源码还是编译时生成的中间代码IL中泛型都是一个占位符,在运行期时,由具体的数据类型替换其占位符再由即时编译器JIT生成实际的代码。然而,Java却不同,只能在源码能看到使用的泛型,经过编译后的class反编译后发现,已经恢复回原生类型,并在后续GetXXXX等方法获取相关数据的时候插入了强制转型代码,此实现方法为类型擦除,也就是业界所称的伪泛型,所以,这颗Java语法糖,够迷惑人么?

 

后面针对伪泛型的引入之后,JCP引入Signature、LocalVariableTypeTable等新属性用于解决伴随泛型而来的参数类型等识别问题的,看着有点懵就没怎么看懂,不过觉得首先还是得找源码及JVM相关书籍看一遍,消化之后或许才能通透点吧,唉~有想法的朋友可到如下网址获取技术文档:http://java.sun.com/docs/books/jvms/  (英文资料,有时间尽量还是得啃点,毕竟英文的资料,最新技术方面远比中文来得迅速给力点)

 

那现在回过头看,采用了泛型的代码与非泛型的代码又有啥区别?

1、嗯,一看就懂!(使用了泛型的,你知道它存放的是啥类型的对象,语义明确,并且取出的元素不必写类型转换直接拿来就可用,编译器会替你插入转型代码来代替你手工转型,非泛型的就得苦逼显式写类型转换了)

2、性能问题,应该差别不大,毕竟采用泛型Or非泛型,编译后的字节码还是一样的

3、其它的一些甜,暂时还没领悟到,所以标题就起名为有点甜吧~

 

附:

 --泛型擦除前的代码

1 public static void main(String[] args) {   
2     Map<String, String> map = new HashMap<String, String>();   
3     map.put("hello""你好");   
4     map.put("how are you?""吃了没?");   
5     System.out.println(map.get("hello"));   
6     System.out.println(map.get("how are you?"));   
7 

 

 --泛型擦除后反编译的代码

1 public static void main(String[] args) {   
2     Map map = new HashMap();   
3     map.put("hello""你好");   
4     map.put("how are you?""吃了没?");   
5     System.out.println((String) map.get("hello"));   
6     System.out.println((String) map.get("how are you?"));   
7 

 

 

作者: Sunshine.Wu 发表于 2011-07-20 01:52 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架