4.泛型与虚拟机

[1]虚拟机中没有泛型,只有普通的类和方法

[2]所有的类型参数都用它们的限定类型替换

无论何时定义一个泛型类型,都自动提供了一个相应的原始类型。原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用 Object)
如Pair的原始类型:

public class Pair {
	private Object first;
	private Object second;
	
	public Pair(Object first, Object second) {
		this.first = first;
		this.second = second;
	}
}

以上是无限定的情况,接下来是有限定的情况。有限定则原始类型用第一个限定的类型变量来替换:

public class Interval<T extends Comparable & Serializable> {
	private T lower;
	private T upper;
	public Interval(T first,T second) {
		...
	}
}

它的原始类型为:

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

[3]为保持类型安全性,必要时插入强制类型转换

如:

Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst();

编译器把这个方法的调用翻译为两条虚拟机指令:
1.对原始方法Pair.getFirst的调用
2.将返回的Object类型强制转换为Employee类型

[4]桥方法被合成来保持多态

class DateInterval extends Pair<LocalDate> {
	public void setSecond(LocalDate second) {
		if(second.compareTo(getFirst()>=0)
			super.setSecond(second);
	}
}

它的原始类型为:

class DateInerval extends Pair {
	public void setSecond(LocalDate second) {...}
}

它从Pair中也继承了一个setSecond方法:
public void setSecond(Object second);
那么

DateInterval interval = new DateInterval(...);
Pair<localDate>pair = interval;
pair.setSecond(aDate);

此时的调用要具有多态性并调用最适合的方法,因此,就需要编译器在DateInterval类中生成一个桥方法:

public void setSecond(Object second) { 
	setSecond((Date) second);
}

首先,变量pair已经声明为类型Pair,并且这个类型只有一个简单的方法叫setSecond,即setSecond(Object)。虚拟机用pair引用的对象调用这个方法。这个对象是DateInterval类型的,因而会调用DateInterval.setSecond(Object)方法。这个方法是合成的桥方法,它调用DateInterval.setSecond(Date),这正是我们所期望的操作效果。

注:本文为《Java 核心技术 卷I》读书笔记及个人理解解释

posted @ 2018-09-10 20:49  肥宅快乐码  阅读(144)  评论(0编辑  收藏  举报