标签:spec private 就会 实现机制 arraylist 问题 定义 擦除 关键字
学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组、无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦);(2)ArrayList<Integer>和ArrayList<String>在运行时的类型是相同的。Java中的泛型有这些问题,是它的实现机制决定的,即“类型擦除”。
public class Holder4<T> {
private T a;
private T b;
private T c;
public Holder4(T a, T b, T c) {
this.a = a;
this.b = b;
this.c = c;
}
public T getA() {
return a;
}
public T getB() {
return b;
}
public T getC() {
return c;
}
public void setA(T a) {
this.a = a;
}
public void setB(T b) {
this.b = b;
}
public void setC(T c) {
this.c = c;
}
public static void main(String[] args) {
Holder4<Automobile> holder4 = new Holder4<>(new Automobile(),new Automobile(), new Automobile());
Automobile a = holder4.getA(); //编译器帮忙转型,不需要显式转型
Automobile b = holder4.getB();
Automobile c = holder4.getC();
}
}
在Java中,每定义一个泛型类型,就会自动提供一个对应的原始类型,例如:
public class Holder4Raw {
private Object a;
private Object b;
private Object c;
public Holder4Raw(Object a, Object b, Object c) {
this.a = a;
this.b = b;
this.c = c;
}
public Object getA() {
return a;
}
public Object getB() {
return b;
}
public Object getC() {
return c;
}
public void setA(Object a) {
this.a = a;
}
public void setB(Object b) {
this.b = b;
}
public void setC(Object c) {
this.c = c;
}
public static void main(String[] args) {
Holder4Raw holder4Raw = new Holder4Raw(new Automobile(),new Automobile(), new Automobile());
Automobile a = (Automobile) holder4Raw.getA(); //显示的转型
Automobile b = (Automobile) holder4Raw.getB();
Automobile c = (Automobile) holder4Raw.getC();
}
}
我们通过字节码进行观察,可以看出:(1)Holder4和Holder4Raw两个类的字节码完全相同;(2)在main函数的33、41和49行就是编译器插入的checkcast语句;
public class org.java.learn.generics.Holder4<T> {
public org.java.learn.generics.Holder4(T, T, T);
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: aload_1
6: putfield #2 // Field a:Ljava/lang/Object;
9: aload_0
10: aload_2
11: putfield #3 // Field b:Ljava/lang/Object;
14: aload_0
15: aload_3
16: putfield #4 // Field c:Ljava/lang/Object;
19: return
public T getA();
Code:
0: aload_0
1: getfield #2 // Field a:Ljava/lang/Object;
4: areturn
public T getB();
Code:
0: aload_0
1: getfield #3 // Field b:Ljava/lang/Object;
4: areturn
public T getC();
Code:
0: aload_0
1: getfield #4 // Field c:Ljava/lang/Object;
4: areturn
public void setA(T);
Code:
0: aload_0
1: aload_1
2: putfield #2 // Field a:Ljava/lang/Object;
5: return
public void setB(T);
Code:
0: aload_0
1: aload_1
2: putfield #3 // Field b:Ljava/lang/Object;
5: return
public void setC(T);
Code:
0: aload_0
1: aload_1
2: putfield #4 // Field c:Ljava/lang/Object;
5: return
public static void main(java.lang.String[]);
Code:
0: new #5 // class org/java/learn/generics/Holder4
3: dup
4: new #6 // class org/java/learn/generics/Automobile
7: dup
8: invokespecial #7 // Method org/java/learn/generics/Automobile."<init>":()V
11: new #6