首先,强调一个观点:java
对于我这样的初学者,必定要站在虚拟机和编译器的角度来分析java 语言的种种特性,泛型也不例外。(我认为这个一条正确的学习经验)程序员
写这篇文章起源于最近在学java,有一天在路上和一个同事在讨论什么是java泛型的时候,发现有些概念很是模糊。因而,我想澄清一下,并记录下来。学习
但愿看过的朋友可以纠正里面的错误。很是感谢。spa
1 关于Java 泛型机制对象
在java 最第一版本,继承
Java 泛型是经过 继承实现的,我认为 这里的继承,不是类的继承而是类型的继承.开发
exampleget
public class Test编译器
{虚拟机
Object var;
Object getVar();
Void setVar( Object );
}
这是一个类.
泛型应用是这样作的
Test testObj= new =Test();
class A
{}
A a = new A();
a = (A)getVar();
由于A类 是Object类的子类,这样的话,经过类型强制转换,就能够实现赋值。
class B ,class C等等 道理同样。
经过这种方式实现和C++ 泛型同样的效果。惟一须要注意的地方在于类型转换,类型判断这些类型相关的操做须要程序员干预。
我猜想,Java 的泛型机制就是创建在类型继承这个基础上,后面版本的泛型 本质上也是这样作的
2 关于泛型的类型擦除
做为一个泛型类的开发人员,咱们定义了一个泛型类,
好比
example
public class Test<T>
{
T var;
T getVar();
Void setVar( T t);
}
说明,这个的T 是一个相对于class Test 的类型参数,(能够类比: 在 void func( int x ) 中,int x是相对于method : func 的类型参数,x 是类型变量同样,)
这个泛型类在编译器中会被作一些处理而生成一个类文件。
选择原始类型(好比Object类),替代 类定义内的全部 T ,
将<T> 抹去
结果是生成的类文件效果等同于
public class Test
{
Object var;
Object getVar();
void setVar( Object t);
}
这个过程就叫作java 泛型类型擦除。
这个过程说明什么呢?
说明对于编译器而言,是不存在什么Test<String>类,Test<Date>类等等的。
对于Test<xx> 各类对象,它们都属于同一个类 Test ;
但要注意,编译器看到泛型格式<T >,编译会作一些额外的事情,好比类型转换,桥方法等等。编译器在这里把之前程序员须要手动作的事情给作。
毕竟程序员写的代码是要给编译器看懂的。经过泛型一些约定的规则,让程序员的意图为编译器所准确知道,这样写出的代码才不会有问题。
3泛型类型的继承问题
首先,继承是一个类,类型之间关系的问题,因此就和对象没有关系.对象之间不存在继承的问题。
在上面的分析中,咱们知道编译器不会产生具体类型参数的类。只会生成一个原始类型的普通类。即只有一个类。
那么这里又何来 泛型类型的继承问题呢?
个人理解是: 类型的继承和类的继承不是同一个概念,应该说,类型继承是类型继承,类继承也是类型继承,但类型继承就不必定是类继承
Texample : Test<String > 是 Test 的一个子类型, 并非: Test<String > 是一个类,Test 是另外一个类,Test<String > 是 Test 的子类.
在继承这个概念中,类型继承是一个超类,而类继承是一个子类。,类继承也是类型继承的一种状况,而不能说由于A类型是继承B类型,就推导出A是一个类,B是另外一个类。A是B的子类。
我不知道UML里面是否是这样定义的。