【问题标题】:cast on object of type superclass returns object of type subclass in java在java中对超类类型的对象进行强制转换返回子类类型的对象
【发布时间】:2015-02-26 22:53:06
【问题描述】:

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

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。

【问题讨论】:

  • 一年中没有更好的时间开始学习Java吗?
  • 为什么不呢?你期望会发生什么? B 覆盖该函数。
  • 没有什么不好的时候开始学习 Java :))
  • 嗯,是的,它覆盖了它,但演员表是针对 A 而不是 B。答案是它在继承线上自下而上的事实吗?换句话说,当我对超类 A 进行强制转换时,它需要 A 的最后一个孩子?

标签: java binding casting subclass superclass


【解决方案1】:

这是一个价格的两个问题。 (1) 为什么我们从 B 类中获取实现,以及 (2) 为什么我们从 A 类型的参数中获取方法的版本。

对于问题(1),要记住的是,当您强制转换对象或将其分配给类型不同的变量时,对象的类不会改变。所以在你的例子中,this 的类总是C,因为那是你创建的。 C 类从 B 类继承其 met(A a) 版本,因为它没有自己的版本,并且因为 B 类已覆盖 A 类中的版本。这就是多态的意义——方法的版本取决于你调用它的对象的class,而不是你使用的表达式的type调用它。

对于问题 (2),在编译时评估方法签名是 Java 的一个小怪癖。所以编译器看到你正在将 type A 的表达式传递到你的方法中,所以它选择签名 met(A a)。因为这个决定是在编译时做出的,所以参数的实际类没有任何区别——编译器已经根据表达式的类型选择了方法。换句话说,Java 没有给你方法参数的多态性。

【讨论】:

    【解决方案2】:

    那么,让我们看看调用:

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

    相当于:

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

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

    int met(A a)
    

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

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

    【讨论】:

      猜你喜欢
      • 2012-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 2015-10-10
      • 1970-01-01
      相关资源
      最近更新 更多