文档章节

java 泛型-擦除erasure

110hxl
 110hxl
发布于 2014/02/11 14:55
字数 832
阅读 196
收藏 6

    类型擦除(type erasure)。 Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个过程就称为类型擦除。如在代码中定义的List<Object>和List<String>等类型,在编译之后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。类型擦除也是Java的泛型实现方式与C++模板机制实现方式之间的重要区别。

    很多泛型的奇怪特性都与这个类型擦除的存在有关,包括:
    泛型类并没有自己独有的Class类对象。比如并不存在List<String>.class或是List<Integer>.class,而只有List.class。
    静态变量是被泛型类的所有实例所共享的。对于声明为MyClass<T>的类,访问其中的静态变量的方法仍然是 MyClass.myStaticVar。不管是通过new MyClass<String>还是new MyClass<Integer>创建的对象,都是共享一个静态变量。

当泛型遇见重载:


public class GenericTypes { 
  public static void method(List<String> list) { 
  System.out.println("invoke method(List<String> list)"); 
 } 
  public static void method(List<Integer> list) { 
  System.out.println("invoke method(List<Integer> list)"); 
 } 
}

    这段代码是不能被编译的,是因为参数List<Integer>和List<String>编译之后都被擦除了,变成了一样的原生类型List<E>,擦除动作导致这两个方法的特征签名变得一模一样。初步看来,无法重载的原因已经找到了,但是真的就是如此吗?只能说,泛型擦除成相同的原生类型只是无法重载的其中一部分原因。

public class GenericTypes { 
  public static String method(List<String> list) { 
  System.out.println("invoke method(List<String> list)"); 
  return ""; 
} 
  public static int method(List<Integer> list) { 
  System.out.println("invoke method(List<Integer> list)"); 
  return 1; 
} 
 public static void main(String[] args) { 
  method(new ArrayList<String>()); 
  method(new ArrayList<Integer>()); 
} 
}
    两个method方法添加了不同的返回值,由于这两个返回值的加入,方法重载居然成功了,即这段代码可以被编译和执行了。这是我们对Java语言中返回值不参与重载选择的基本认知的挑战吗? 

    重载当然不是根据返回值来确定的,之所以这次能编译和执行成功,是因为两个mehtod()方法加入了不同的返回值后才能共存在一个Class文件之中。Class文件方法表(method_info)的数据结构时曾经提到过,方法重载要求方法具备不同的特征签名,返回值并不包含在方法的特征签名之中,所以返回值不参与重载选择,但是在Class文件格式之中,只要描述符不是完全一致的两个方法就可以共存。也就是说两个方法如果有相同的名称和特征签名,但返回值不同,那它们也是可以合法地共存于一个Class文件中的。



本文转载自:http://kimibob.blog.163.com/blog/static/163873051201221042151904/

上一篇: java泛型 wildcard
下一篇: 泛型小记
110hxl
粉丝 6
博文 211
码字总数 54059
作品 0
深圳
程序员
私信 提问
尝试Java,从入门到Kotlin

之前一直使用C#开发,最近由于眼馋Java生态环境,并借着工作服务化改造的契机,直接将新项目的开发都转到Java上去。积攒些Java开发经验,应该对.NET开发也会有所启发和益处。 欢迎工作一到八...

编程SHA
2018/12/03
24
1
【转】Java语法糖的味道:泛型与类型擦除

泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类...

mj4738
2011/11/29
318
0
Java 泛型,你了解类型擦除吗?

泛型,一个孤独的守门者。 大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个...

xiaomin0322
2018/06/06
30
0
Java深度历险 Java泛型

Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter)。声明的类型参数在使用时用具体的类型来替换。泛型最主要的应用是在JDK 5中的新集...

SeanCai
2011/03/03
1K
2
【J2SE】JAVA语法糖之-伪泛型

JAVA语法糖之-伪泛型 泛型即参数化类型 首先看一个泛型例子: public static void main(String[] args) {List<String> strList = new ArrayList<String>();strList.add("generic test!");fo......

磊神Ray
2011/09/28
664
0

没有更多内容

加载失败,请刷新页面

加载更多

CSS--列表

一、列表标识项 list-style-type none:去掉标识项 disc:默认实心圆 circle:空心圆 squire:矩形 二、列表项图片 list-style-img: 取值:url(路径) 三、列表项位置 list-style-position:...

wytao1995
今天
6
0
linux 命令-文本比较comm、diff、patch

本文原创首发于公众号:编程三分钟 今天学了三个文本比较的命令分享给大家。 comm comm 命令比较相同的文本 $ cat charabc$ cat chardiffadc 比如,我有两个文件char和chardiff如上,...

编程三分钟
今天
7
0
QML教程

https://blog.csdn.net/qq_40194498/article/category/7580030 https://blog.csdn.net/LaineGates/article/details/50887765...

shzwork
今天
5
0
HA Cluster之5

对于使用heartbeat v2版的CRM配置的集群信息都是保存在一个名为cib.xml的配置文件中,存放在/var/lib/heartbeat/crm/下。CIB:Cluster Information Base,由于xml文件配置不是那么方便,所以...

lhdzw
今天
6
0
玩转Redis-Redis基础数据结构及核心命令

  《玩转Redis》系列文章主要讲述Redis的基础及中高级应用,文章基于Redis5.0.4+。本文主要讲述Redis的数据结构String,《玩转Redis-Redis基础数据结构及核心命令》相关操作命令为方便对比...

zxiaofan666
今天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部