从头认识java-13.6 类型擦除(type erasure)

这一章节我们讨论一下类型擦除。

1.什么是类型擦除?

在java里面泛型其实是伪泛型,因为他都只是在编译器里面实现的,在jvm里面是没有泛型的概念。

我们看下面的代码:

package com.ray.ch11;

import java.util.ArrayList;

public class Test {
	public static void main(String[] args) {
		ArrayList<Integer> list1 = new ArrayList<Integer>();
		ArrayList<String> list2 = new ArrayList<String>();
		System.out.println(list1.getClass() == list2.getClass());
	}
}

输出:

true


为什么两个list对应的Class对象是一致的呢?因为在jvm层面,他只看到List,没有里面的类型。

也就是,泛型里面的类型信息被擦掉了,这就是所谓的类型擦除。

 

2.扩展

我们使用另一个例子来扩展开来。

package com.ray.ch11;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;

public class Test {
	public static void main(String[] args) {
		ArrayList<Integer> list = new ArrayList<Integer>();
		HashMap<String, String> map = new HashMap<String, String>();
		HashSet<String> set = new HashSet<String>();
		System.out
				.println(Arrays.toString(list.getClass().getTypeParameters()));
		System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
		System.out.println(Arrays.toString(set.getClass().getTypeParameters()));
	}
}


输出:

[E]
[K, V]
[E]


从上面的输出,我们只是看见泛型的标记,但是完全不问清楚里面的类型信息,这是因为代码经过编译器后,类型信息被擦除了。

 

总结:这一章节我们引出类型擦除的概念。

 

这一章节就到这里,谢谢。

-----------------------------------

目录


 

### 回答1: Java类型擦除是指在编译时期将泛型类型信息擦除掉,使得运行时期无法通过反射获取泛型的类型信息。这是为了保持Java的向后兼容性,因为Java的泛型是在Java 5之后才被引入的,如果在编译器中完全支持泛型类型信息,那么早期的Java代码将无法运行。 当我们使用Java的泛型时,编译器会将泛型类型擦除成其上限边界(upper bound)或Object类型(如果没有指定上限边界),并在编译时检查泛型类型类型安全性。在运行时期,所有泛型类型都将被擦除为其上限边界或Object类型。 例如,考虑以下代码: ``` List<String> list = new ArrayList<String>(); list.add("Hello"); String s = list.get(0); ``` 在编译时期,编译器会将代码转换为: ``` List list = new ArrayList(); list.add("Hello"); String s = (String) list.get(0); ``` 在这个示例中,List<String> 被擦除为 List,String擦除为 Object,并且编译器在使用 list.get(0) 时插入了强制类型转换。 Java类型擦除机制可以使得泛型类型在运行时期不需要重新编译,从而提高了Java程序的性能和可维护性。但是,在某些情况下,类型擦除也可能导致一些问题,例如无法在运行时期获取泛型类型信息。为了解决这些问题,Java提供了反射机制,可以在运行时期获取泛型类型信息。 ### 回答2: Java类型擦除机制(Type Erasure)是Java编译器为了保持向后兼容性而采用的一种编译时处理泛型类型的方式。 Java的泛型是在JDK 5中引入的,旨在提供更强类型检查和更好的代码可读性。泛型的核心概念是参数化类型,即可以在类、接口、方法的定义中使用类型参数。例如,我们可以定义一个List<T>类型的类,其中的T表示类型参数,可以在初始化列表对象时指定具体类型,如List<Integer>、List<String>等。 但是,这种泛型类型在编译后的字节码文件中会被擦除,即所有的类型参数都会被替换成它们的上界或Object类型。也就是说,List<T>在字节码文件中会变成List<Object>。这就是类型擦除机制。 类型擦除机制带来的好处是保持了编译后的字节码文件与之前不使用泛型的代码的兼容性,因为老的Java虚拟机可以无需特殊处理就可以加载泛型类的实例。 在泛型类或方法内部,由于类型擦除,无法获得泛型参数的具体类型信息。这就限制了在运行时对泛型类型的操作。但是,为了提供类似的功能,Java引入了类型通配符和反射机制。 除了泛型类和方法,类型擦除机制还适用于泛型接口、泛型数组等。 总结来说,Java类型擦除机制是为了保持向后兼容性而在编译过程中擦除泛型类型的实际类型参数,替换为具体类型的上界或Object类型。这使得泛型类型在运行时无法获得具体类型信息,但通过类型通配符和反射机制仍然可以在一定程度上实现类似的功能。 ### 回答3: Java类型擦除机制是指在泛型代码编译后,会将泛型类型擦除为其边界或Object类型,以确保泛型代码能够与旧版的Java代码进行兼容。下面我将详细介绍Java类型擦除机制。 在Java中,泛型类或泛型方法可以使用类型参数来定义,用于表示一般化的数据类型。例如,我们可以定义一个泛型类`MyList<E>`,其中`E`表示元素类型。在泛型类的内部,我们可以使用类型参数`E`代表任意数据类型。 然而,当Java编译器编译泛型代码时,它会将类型参数擦除并替换为其边界或Object类型。也就是说,编译后的代码不会保留泛型中的具体类型信息。这是为了确保泛型代码与之前的非泛型代码兼容。类型擦除机制的实现主要有以下几个方面: 1. 擦除泛型中的类型参数:编译器会将泛型类或泛型方法中的类型参数`E`擦除为Object类型。这意味着在运行时,无法获取具体的泛型类型。 2. 插入类型转换代码:当使用泛型时,编译器会在需要的地方插入类型转换代码,以确保类型安全。这些转换代码在编译时由编译器自动生成。 3. 边界类型擦除:如果类型参数有边界约束,例如`<E extends Number>`,则编译器会擦除为边界类型,即`<E extends Number>`会被擦除为`<E extends Number>`。 4. 桥方法生成:当泛型类或泛型接口实现了泛型方法时,编译器会为了保持类型安全生成桥方法。桥方法的作用是在类型擦除后保留泛型方法的类型信息。 综上所述,Java类型擦除机制通过将泛型代码中的类型参数擦除为边界类型或Object类型,以确保泛型代码与旧版的非泛型代码兼容。类型擦除机制是Java泛型的一种实现方式,它在编译时确保类型安全,在运行时无法获取具体的泛型类型信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值