泛型类
——代码参考:java核心技术 卷1 第十版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class Pair<T> { private T first; private T second; //构造器 public Pair() { first = null ; second = null ;} public Pair(T first , T second ) { this .first = first; this .second = second;} //get方法 public T getFirst() { return first; } public T getSecond () { return second;} //set方法 public void setFirst(T newValue) { first =newValue; } public void setSecond (T newValue) { second = newValue; } } |
泛型方法
1
2
3
4
5
|
class A public static <T> T get(T a) { return a; } |
泛型方法可以定义在普通类中,也可定义在泛型类中。
类型擦除(Type Erasure)
以下内容参考自—— [Java泛型与桥方法]
JVM并不知道泛型的存在,因为泛型在编译阶段就已经被处理成普通的类和方法; 处理机制是通过类型擦除,擦除规则:
- 若泛型类型没有指定具体类型,用Object作为原始类型;
- 若有限定类型< T exnteds XClass >,使用XClass作为原始类型;
- 若有多个限定< T exnteds XClass1 & XClass2 >,使用第一个边界类型XClass1作为原始类型;
例如:上述泛型类Pair编译后的结果为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class Pair { private Object first= null ; private Object second= null ; public Pair(Object fir,Object sec) { this .first=fir; this .second=sec; } public Object getFirst() { return this .first; } public void setFirst(Object fir) { this .first=fir; } } |
类型擦擦会带来一些问题,比如当一个类实现了一个参数化的接口或是继承了一个参数化的类时。
1
2
3
4
|
class SonPair extends Pair<String> //继承类一个泛型类 { public void setFirst(String fir){....} //重写了父类的方法 } |
Pair在编译的时候已经被类型擦除,Pair的setFirst方法变为了setFirst(Object fir),这样SonPair的setFirst(Stirng fir)方法就无法覆盖父类中的setFirst(Object fir)方法,因为参数不同,不是同一个方法。 如下所示,SonPair中会出现两个方法:
1
2
|
public void setFirst(String fir){....} public void setFirst(Object fir){....} |
那么具体应该调用哪一个方法呢? 为了解决这个问题,jvm引进了桥方法的概念
桥方法
上一节中的两个方法被编译器变成了这样:
1
2
3
4
5
6
7
|
public void setFirst(String fir){....} //这里什么都不变 //为该方法添加了一些东西,该方法就被称为“桥方法” public void setFirst(Object fir) { setFirst((String) fir); //桥内部调用的是子类中定义的setFirst(String fir)方法 } |