基础知识-Java泛型擦除(简洁明了)


0.概念

Java 泛型的参数只可以代表类,不能代表个别对象。由于 Java 泛型的类型参数之实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型。Java 编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。

---百度百科

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

---百度百科

JVM并不知道泛型的存在,因为泛型在编译阶段就已经被处理成普通的类和方法;
处理机制是通过类型擦除,擦除规则:

若泛型类型没有指定具体类型,用Object作为原始类型;
若有限定类型< T exnteds XClass >,使用XClass作为原始类型;
若有多个限定< T exnteds XClass1 & XClass2 >,使用第一个边界类型XClass1作为原始类型;

1.泛型擦除的体现

 在写代码时,无法把一个 String 类型的实例加到 ArrayList 中,因为ArrayList 和 ArrayList 在编译的时候是完全不同的类型,但是运行结果却是true。这就Java泛型的类型擦除造成的

类加载器把 ArrayList.class文件加载进jvm之后,只会存在一份地址相同的ArrayList的Class类,所以虽然编译时是List 和 List,但是运行时泛型擦除了,他们的class类(也就是getClass()方法获得的)都是同一个,在编译完成后都会被编译器擦除成了 ArrayList(地址也相同)。只不过该Class类有两个实例对象l1和l2而已,两个实例对象的地址不同

Java 泛型擦除是 Java 泛型中的一个重要特性,其目的是避免过多的创建类(这里指类加载器加载的Class类对象,只有一份)而造成的运行时的过度消耗。所以,像ArrayList 和 ArrayList 这两个实例,其类实例(Class类)是同一个。也就是同一个Class类实例产生了ArrayList 和 ArrayList 两个实例对象,Class类实例地址是同一个,两个实例对象的地址不同,即上图会出现:l1.getClass() == l2.getClass() 返回true,但是l1 == l2 返回false.

2.把Activity对象放进List集合里

当我们正常的将 Activity 对象放进 List list = new ArrayList<>( ) 这样的集合去,编译就会报一个错:

泛型的约束让我们无法将 Activity 对象放进泛型为 String 的集合中去。那么咋整呢?

通过泛型擦除的体现已经知道ArrayList(或者ArrayList)编译后都是java.util.ArrayList,泛型的约束是在编译时约束的,真正运行的 class 是没有泛型约束的。所以只要在运行时将 Activity 对象加入List中就可以了:

转载:https://blog.csdn.net/qq_30878303/article/details/79639904

TRANSLATE with x English
Arabic Hebrew Polish
Bulgarian Hindi Portuguese
Catalan Hmong Daw Romanian
Chinese Simplified Hungarian Russian
Chinese Traditional Indonesian Slovak
Czech Italian Slovenian
Danish Japanese Spanish
Dutch Klingon Swedish
English Korean Thai
Estonian Latvian Turkish
Finnish Lithuanian Ukrainian
French Malay Urdu
German Maltese Vietnamese
Greek Norwegian Welsh
Haitian Creole Persian  
Bing Webmaster Portal Back