类型擦除与桥接方法
Java中类型擦除与桥接方法
- Java语言是不根据返回值类型来判定是否为方法的重载的
- 方法签名 = 方法名 + 参数类型
- 但是JVM却是把返回值类型当做判定条件的
- 方法签名 = 方法名 + 参数类型 + 返回值类型
可能出现的问题.
- 如果说子类重写父类方法,返回值类型改变了.对于Java来讲是重写,但是对于JVM却不是.
- 另外在使用泛型时,父类T,子类重写父类方法在类型擦除时,方法签名也会改变.
- 所以在子类重写父类方法时,如果有上述情况,则会出现桥接方法.
下面,我以类型擦除为例,简单了解一下桥接方法
Node类
package bm;
public class Node<T> {
public T data;
public Node(T data){
this.data = data;
}
public void setData(T data) {
this.data = data;
System.out.println("Node: data = "+data);
}
}
MyNode类
package bm;
public class MyNode extends Node<Integer>{
public MyNode(Integer data) {
super(data);
}
public void setData(Integer data){
System.out.println("Node: data = "+data);
}
}
测试代码
public static void main(String[] args) {
MyNode myNode = new MyNode(12);
//原始类型,会有个warning
Node node = myNode;
//类型转换异常
node.setData("hello");
Integer x = myNode.data;
}
在类型擦除之后,上面的代码变成了
public static void main(String[] args) {
MyNode myNode = new MyNode(12);
//原始类型,会有个warning
Node node = (MyNode)myNode;
node.setData("hello");
//类型转换异常
Integer x = (String)myNode.data;
}
错误的原因
- 就是类型转换错误.node引用了myNode
- 虽然调用了setData(),但是是父类的.
类型擦除后的两个类
Node中的泛型参数T 变成了 Object
这样MyNode就不再是重写父类的方法了
public class Node {
public Object data;
public Node(Object data) { this.data = data; }
public void setData(Object data) {
this.data = data;
}
}
public class MyNode extends Node {
public MyNode(Integer data) { super(data); }
public void setData(Integer data) {
super.setData(data);
}
}
为了解决这种情况和维持多态性,所以编译器就提供了桥接方法(自动生成)
class MyNode extends Node {
// 桥接方法,被编译器自动生成
public void setData(Object data) {
setData((Integer) data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
// ...
}