为什么Java编译器为无参数的方法(getter方法)创建桥接方法

问题描述 投票:0回答:1

我确实理解需要创建桥接方法,例如需要传递参数的 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 类的子类(协变返回类型) 所以看起来重写已经完成了。为什么需要桥接方法? 我错过了什么?

java generics overriding bridge
1个回答
0
投票

“...我确实理解需要创建桥接方法,例如 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。

© www.soinside.com 2019 - 2024. All rights reserved.