8.5.1类型擦除

8.5泛型代码和虚拟机

虚拟机中并不存在泛型类型的对象——虚拟机中所有的对象都是普通类类型的。下面讲解编译器是如何“擦除”类型参数的,类型擦除又对我们程序员有什么影响。

8.5.1 类型擦除(编译器对泛型类的处理)

当你定义一个泛型类型的时候,一个对应的原始类型(raw type)会自动生成。这个原始类型跟对应的泛型类型①名称相同,②删除了类型参数,③类型变量被替换成它的边界列表中的第一个边界(无边界的类型变量被替换为Object).
例如,Pair<T>的原始类型如下:

public class Pair{
	private Object first;
	private Object second;
	
	public Pair(Object first, Object second){
		this.first = first;
		this.second = second;
		} 
	
	public Object getFirst(){return first;}
	public Object getSecond(){return second;}
	
	public void setFirst(Object newValue){first = newValue;}
	public void setSecond(Object newValue){second = newValue;}
	}

被编译器处理后的泛型类最后就成了一个普通类,在没有泛型的时代里我们就是这么实现通用的Pair的。
程序中的Pair<String>,Pair<LocalDate>等各种泛型Pair,最终都被擦除成为原始类型Pair。

C++Note:
C++中一个模板的每种实例都会对应产生一种类型,无疑增加了最终程序的代码行,Java就没有这个毛病

同理

public class Interval<T extends Comparable&Serializable> implements Serializable{
	private T lower;
	private T upper;
	...
	public Interval(T first, T second){
		if(first.compareTo(second) <= 0){lower = first; upper = second;}
		else{lower = second; upper = first;}
		}
	}

擦除后变为原始类型

public class Interval implements Serializable{
	private Comparable lower;
	private Comparable upper;
	...
	public Interval(Comparable first, Comparable second){...}
	}

Note
如果一个类型参数有多个边界,则类型变量会被替换成边界列表中的第一个边界,在必要时,编译器会插入cast将类型变量cast为其他边界类型,在上面的例子中,如果把边界Serializable放在前面,那么在compareTo方法中,方法的形参就会被cast为Comparable类型。所以:标签接口(标签接口是没有方法的接口)边界应该尽可能放在列表后面,方法被使用较多的边界则放在前面,这样可以减少cast的次数,提高效率。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值