我确实理解需要创建桥接方法,例如需要传递参数的 setter 方法,但是 getter 方法呢?为什么Java也产生桥接方法?
这里是 ChatGPT 生成的虚拟代码,以使事情更加具体:
class Box<T> {
private T value;
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
class StringBox extends Box<String> {
public void setValue(String value) {
System.out.println("Setting a String value in StringBox");
super.setValue(value.toString());
}
public String getValue() {
System.out.println("Getting String value from StringBox");
return super.getValue();
}
}
擦除后的Box类会有如下方法:
public Object getValue();
在StringBox类中,我们定义了方法:
public String getValue()
但这两个方法具有相同的签名,并且重写方法的返回类型使用 String 作为返回类型,它是 Object 类的子类(协变返回类型)
所以看起来重写已经完成了。为什么需要桥接方法?
我错过了什么?
“...我确实理解需要创建桥接方法,例如 setter 方法...”
下面的 Java 教程描述了这种情况。
类型擦除和桥接方法的效果(Java™ 教程 > 学习 Java 语言 > 泛型(已更新))。
...类型擦除后,方法签名不匹配; Node.setData(T) 方法变为 Node.setData(Object)。因此,MyNode.setData(Integer) 方法不会覆盖 Node.setData(Object) 方法。
为了解决这个问题并在类型擦除后保留泛型类型的多态性,Java编译器生成了一个桥接方法来确保子类型按预期工作。
对于 MyNode 类,编译器为 setData 生成以下桥接方法:class MyNode extends Node { // Bridge method generated by the compiler // public void setData(Object data) { setData((Integer) data); } public void setData(Integer data) { System.out.println("MyNode.setData"); super.setData(data); } // ... }
桥接方法 MyNode.setData(object) 委托给原始 MyNode.setData(Integer) 方法。结果,n.setData(“Hello”);语句调用方法 MyNode.setData(Object),并抛出 ClassCastException,因为“Hello”无法转换为 Integer。