类型擦除

今天学习了关于Java泛型的相关知识,在关于类型擦除一节中得到了一些理解。

对于JVM而言,不存在泛型这一概念,对于所有的泛型类,都会被转化为普通类(其中无限定泛型会被转化为Object,而限定泛型会被转化为限定类(接口)),而正是因为这种转化会导致在子类的方法覆写上会出现问题,下面举一个例子:

1
2
3
4
5
6
7
8
9
10
class Example<T> {
T data;
//getter and setter
public void setData(T data) {
this.data = data;
}
public T getData() {
return data;
}
}

类型擦除后:

1
2
3
4
5
6
7
8
9
10
class Example {
Object data;

public void setData(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
}

现在有一子类:

1
2
3
4
5
6
7
8
9
10
class SubClass extends Example<String> {

public void setData(String data) {
//...
}

public String getData() {
//...
}
}

对应类型擦除后:

1
2
3
4
5
6
7
8
9
10
class SubClass extends Example {

public void setData(String data) {
//...
}

public String getData() {
//...
}
}

奇怪的知识增加了…

其中,我们会发现,在父类方法中的getter/setter的方法参数为Object,而在子类当中,其方法参数为Sting!这不应该是方法覆写,而应该是方法重载啊!这样不就失去了其多态性么?

实则不然,Java编译器会自动在编译时在子类中生成一个桥方法,例如:

1
2
3
public void setData(Object data){
setData((String) data);
}

注意:这是编译器自动生成的,若是在子类中直接写出,会提示报错

相同实现,但没有覆盖…以上便是,类型擦除与多态冲突的解决之道。