何为泛型擦除
来源:互联网 发布:java多线程运用场景 编辑:程序博客网 时间:2024/05/23 13:08
何为泛型擦除
要理解泛型的擦除,首先要知道泛型的产生。
泛型是JDK1.5才添加到Java中的,也就是说JDK1.5之前是没有泛型这一说的。例如:Comparable接口在JDK1.5之前是如下定义的:
public interface Comparable {
public int compareTo(Object o)
}
在JDK1.5或之后就采用了泛型,具体如下:
public interface Comparable<T> {
public int compareTo(T o)
}
Java作为一门程序设计语言,需要保证没有使用泛型的代码能在JDK1.5及以后的VM上运行,也就是兼容性的问题。
为了解决这种代码的的兼容性,Java提供了泛型擦除(Erasure)。下面先看一个例子:
程序清单1 TestGenericErased.java
import java.util.ArrayList;import java.util.List;/** * @author Administrator * */public class TestGenericErased {public static void main(String[] args) {List<String> list1 = new ArrayList<String>();list1.add("solo");List<Integer> list2 = new ArrayList<Integer>();list2.add(999);System.out.println("-------------------");System.out.println("输出字符串:" + list1);System.out.println("输出整数:" + list2);System.out.println("-------------------");System.out.println(list1.getClass());System.out.println(list2.getClass());System.out.println("-------------------");System.out.println("判断list1和list2两个列表的类是否相同:" + (list1.getClass() == list2.getClass()));}}
运行结果:
-------------------输出字符串:[solo]输出整数:[999]-------------------class java.util.ArrayListclass java.util.ArrayList-------------------判断list1和list2两个列表的类是否相同:true
上面的代码有两个不同的ArrayList:ArrayList<Integer>和 ArrayList<String>,前一个是保存整数的列表,后一个事保存字符串的列表,是两个具有不同参数化类型的ArrayList。但是通过比较它们的 Class 对象,运行结果输出的是 true。这说明在代码运行过程中,JVM虚拟机将它们视为同一个类:class java.util.ArrayList。
为什么会是这样的结果呢?编译器做了什么?
为了解决前面所说的兼容性问题,编译器需要做一些擦除的工作,通俗地说:编译器擦除掉在代码中与泛型类型有关的信息,这样最后生成出来的代码(字节码文件)其实是没有了泛型的代码,也就是说泛型基本上由编译器来实现,由编译器执行类型检查和类型推断,然后在生成字节码之前将其清除掉,虚拟机并不知道也不关心是否存在泛型。这样的话,泛型和非泛型的代码就可以混合运行,保证了代码的兼容性。
还需要说明的是:在使用泛型时,会有一个对应的类型叫做原生类型(raw type),泛型类型会被擦除到原生类型,例如:前面的代码中,ArrayList<String>()会被擦除到ArrayList,ArrayList<Integer>()被擦除到ArrayList,由于擦除,在虚拟机中无法获得任何类型信息,虚拟机只知道原生类型。
为了更进一步了解擦除,下面使用DJ Java Decompiler反编译工具对TestGenericErased.java源文件编译后的TestGenericErased.class字节码文件进行反编译,其反编译的代码如下:
程序清单2 TestGenericErased.class反编译后的代码
// Decompiled by DJ v3.12.12.100 Copyright 2015 Atanas Neshkov Date: 2017/11/18 星期六 17:39:45// Home Page: http://www.neshkov.com/dj.html - Check often for new version!// Decompiler options: packimports(3) // Source File Name: TestGenericErased.javaimport java.io.PrintStream;import java.util.ArrayList;import java.util.List;public class TestGenericErased{ public TestGenericErased() { } public static void main(String args[]) { ArrayList arraylist = new ArrayList(); arraylist.add("solo"); ArrayList arraylist1 = new ArrayList(); arraylist1.add(Integer.valueOf(999)); System.out.println("-------------------"); System.out.println((new StringBuilder()).append("\u8F93\u51FA\u5B57\u7B26\u4E32\uFF1A").append(arraylist).toString()); System.out.println((new StringBuilder()).append("\u8F93\u51FA\u6574\u6570\uFF1A").append(arraylist1).toString()); System.out.println("-------------------"); System.out.println(arraylist.getClass()); System.out.println(arraylist1.getClass()); System.out.println("-------------------"); System.out.println((new StringBuilder()).append("\u5224\u65ADlist1\u548Clist2\u4E24\u4E2A\u5217\u8868\u7684\u7C7B\u662F\u5426\u76F8\u540C\uFF1A").append(arraylist.getClass() == arraylist1.getClass()).toString()); }}
对比程序清单1和程序清单2,在程序清单2中没有了泛型,程序又回到Java泛型出现之前的写法,泛型类型都变回了原生类型ArrayList,具体是:
程序清单1
程序清单2
List<String>
ArrayList
ArrayList<String>()
ArrayList
List<Integer>
ArrayList
ArrayList<Integer>()
ArrayList
参考网址:
1.https://www.cnblogs.com/drizzlewithwind/p/6101081.html
2.http://justjavac.iteye.com/blog/1741638
3.http://blog.csdn.net/lonelyroamer/article/details/7868820
4.https://www.cnblogs.com/xltcjylove/p/3671943.html
5.https://www.cnblogs.com/LinkinPark/p/5232980.html
6.http://blog.sina.com.cn/s/blog_7ffb8dd501012ku9.html
7.http://blog.csdn.net/yuhongye111/article/details/39104601
- 何为泛型擦除
- 泛型的擦除
- JAVA泛型擦除
- Java泛型擦除
- Java泛型擦除
- Java泛型擦除
- Java泛型擦除
- Java泛型擦除
- JAVA泛型擦除
- Java 泛型擦除
- 泛型擦除补偿
- 泛型擦除
- 泛型擦除机制
- 详解泛型擦除
- 泛型的擦除
- 关于泛型擦除
- 泛型及其擦除
- 泛型类型擦除
- HDOJ 2017 ,祝你AC
- python3 XML转Json
- tomcat7:run ClassCastException解决
- java实现不固定行列数excel导出
- C语言整数的因式分解
- 何为泛型擦除
- zipimport.ZipImportError: can't decompress data; zlib not available 解决
- ARM GUN汇编标准
- ListIterator的双向遍历
- 产看系统硬件版本位数,查看操作系统版本,查看内核版本
- ArcGIS连接自编译PostgreSQL数据库
- JAVA字符集
- jvm编译运行(1)
- 实验六 树和二叉树的实验2