jdk5加入泛型,泛型实现了参数化类型,使代码可以应用与多种类型,其目的是希望类或方法能够具备最广泛的表达能力。
基于上述的目的,考虑如果自己实现语言的泛型机制,该怎么做。考虑下列问题:
1.是不是在设计语言的初期加入,或者是在后期加入,需要保持向前的兼容性
2.在编译期进行处理,或者在运行期处理(假定语言有这两部分组成)
3.怎么保证虚拟机和执行环境能正确的处理泛型
下面我的想法:
1.在编译器编译的时候,执行对类型参数的检查,以及用到类型参数的具体参数类型,为每一份具体调用生成单独的处理,这个很简单。或者在运行期动态的调用动态产生的程序
2 泛型和非泛型这么转化,在语言初期设计可以不用考虑,直接看成int和double就是了,但在后期必须有个转化点,或者说交换点,如java的泛型容器和非泛型容器的兼容
3 在语言的处理内部怎么表示参数化类型,这个搞到就能正确的处理泛型
以上是自己的胡乱猜测,下面进去java的泛型:
java使用运行期的擦除实现泛型,在运行时类型参数已经被擦除,在运行时没有任何泛型的消息了,它退化成他的一个边界了。java主要是为了向前的兼容性才使用擦除进行泛型设计的。
因为擦除,泛型在显式运行时类型的操作就不能使用了,例子:
public class Test {
public static void main(String[] args) {
/**
* 大家都是ArrayList,只是打扮不同嘛
*/
Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1==c2);
}
}
你可以看到在运行期具体的类型参数被擦除,但是你可以得到类型参数的标识和类型边界参数
不能创建泛型话数组使用Array.newInstance()然后转型是个办法,意思是我只是个object[],只不过里面存储的是可以表示为类型参数所表示的类型,所以可以进行转型。
关于通配符的使用两例子:
List<? extends Fruit> list
list代表是一个添加Fruit子类的容器,然后悲剧了,虚拟机不知道是具体哪个,所以索性来个编译错误了,这样的只可以取出来,不可以放进去
List<? super Fruit> list,这个容器可以放进去Fruit及其子类,其他的因为边界的问题方不进去了鸟
本人认为java泛型带来的仅有的好处:增加编译器的类型检查,使得编写使用容器类的代码清晰。