java - 对父类(super class)类型的对象进行强制转换在 Java 中返回子类类型的对象

标签 java binding casting subclass superclass

为了理解静态绑定(bind)和动态绑定(bind)的区别,我实现了以下代码:

class A {

    int met(A a) {
        return 0;
    }

    int met(B b) {
        return 1;
    }

    int met(C c) {
        return 2;
    }
}

class B extends A {

    int met(A a) {
        return 3;
    }

    int met(B b) {
        return 4;
    }

    int met(C c) {
        return 5;
    }
}

class C extends B {

    int f() {
        return ((A)this).met((A)this);
    }
}

public class Test {

    public static void main(String[] args) {

        C x = new C();
        System.out.println(x.f());
    }
}

我得到的结果是 3,但我不明白为什么,因为第一次转换为 A。

最佳答案

那么,让我们看看这个调用:

((A)this).met((A)this);

相当于:

A target = this;
A argument = this;
target.met(argument);

因此,对于最后一行,编译器根据所涉及的编译时类型查找签名 - 它将在A(和父类(super class))中查找一个名为 met 的方法,其参数与 A(参数的编译时类型)兼容。重载解析发现答案是:

int met(A a)

这是在编译时确定的签名。但是,该方法的实现是在执行时根据方法调用的执行时目标确定的。该类型在这里是 C - 因为 this 是对 C 实例的引用。 (f 方法在 C 的实例上调用。)

现在 C 不会覆盖 int met(A a),但是 B(它的父类(super class))会覆盖 - 所以这就是实现用过的。 B 覆盖 met(B b)met(C c) 并不重要,因为编译器已经确定正在调用的是 met(A a) 方法。

关于java - 对父类(super class)类型的对象进行强制转换在 Java 中返回子类类型的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27711133/

相关文章:

java - 将 wav/wave 文件读取到短[]数组中

c# - 如何将 DataTrigger 值设置为常量字段?

c# - 更改集合时触发方法

java - 在 Java 中转换对象

oracle - 为什么 CAST 截断文本而不是抛出错误?

java - Mule/Spring - 在 Java 中调用通知对象

java - 在@Service中创建ObjectMapper的@Bean时出错

java - List<?> 的 Lambda 等效项使用属性 A 进行比较并返回属性 B

wpf - 将控件的当前实例绑定(bind)到附加属性

Java,如何根据其接口(interface)之一重新转换对象?