当前位置: 首页 > 面试题库 >

Java:当B扩展A时,A x =新A()与A x =新B()之间的差异

琴光亮
2023-03-14
问题内容

我正在学习Java,但有两个问题:

  1. 之间有什么区别?
    A x = new A();
    

    A x = new B();

考虑到:

    class A
class B extends A
  1. 之间有什么区别:
    A x = new B();
    

    (A)x.run_function();

假设A和B都具有函数run_function,将执行哪个函数?


问题答案:

最重要的区别在于对象的静态和动态类型与对象的引用之间。

说B延伸A,C延伸B。

对象的动态类型(新类型中使用的类型)是其实际的运行时类型:它定义了对象的实际方法。

对象引用(变量)的静态类型是编译时类型:它定义或声明可以在变量引用的对象上调用哪些方法。

变量的静态类型应始终与它引用的对象的动态类型相同或为父类型。

因此,在我们的示例中,静态类型为A的变量可以引用动态类型为A,B和C的对象。静态类型为B的变量可以引用动态类型为B和C的对象。静态类型为C的变量只能引用具有动态类型的对象。动态类型C。

最后,在对象引用上调用方法是静态和动态类型之间的微妙而复杂的交互。(如果您不相信我,请阅读有关方法调用的Java语言规范。)

例如,如果A和B都实现方法f(),并且静态类型为A,而动态类型为C,则调用方法Bf():

B extends A, C extends B
public A.f() {}
public B.f() {}
A x = new C(); // static type A, dynamic type C
x.f(); // B.f() invoked

大大简化:首先,使用接收者(类型A)和参数(没有参数)的静态类型来确定该特定调用的最佳匹配(最特定)方法签名,这是在编译时完成的。在这里,这显然是Af()。

然后,在运行时的第二步中,使用动态类型来定位方法签名的实际实现。我们从C类型开始,但是没有找到f()的实现,因此我们上移到B,并且那里有一个与Af()签名匹配的方法Bf()。因此Bf()被调用。

在我们的示例中,我们说方法Bf()覆盖了方法Af()。类型层次结构中覆盖方法的机制称为子类型多态。



 类似资料:
  • 假设我有下面的代码... 不管类ImplementTwo是同时实现B和A,还是只实现B,它仍然需要在接口A中实现方法A(),因为接口B扩展了接口A。有什么理由显式地这样做吗 而不只是 ?

  • 问题内容: 我尝试了一些代码,使用XOR在Java中交换两个整数而不使用第三个变量。 这是我尝试的两个交换函数: 这段代码产生的输出是这样的: 我很好奇,为什么这样说: 与这个不同吗? 问题答案: 问题是评估的顺序: 参见JLS第15.26.2节 首先,对左操作数求值以产生一个变量。 如果该评估突然完成,则赋值表达式由于相同的原因而突然完成;右边的操作数不会被评估,并且不会发生赋值。 否则,将保存

  • 问题内容: 今天,我发现了python语言一个有趣的“功能”,这让我感到非常悲伤。 那个怎么样?我以为两者是等同的!更糟糕的是,这是我调试时遇到的麻烦的代码 WTF!我的代码中包含列表和字典,并且想知道我到底怎么把dict的键附加到列表上而又没有调用.keys()。事实证明,这就是方法。 我认为这两个陈述是等效的。即使忽略这一点,我也可以理解将字符串追加到列表的方式(因为字符串只是字符数组),但是

  • 问题内容: 我目前正在尝试了解在自定义类上使用和之间的区别。有许多网站说使用’+’运算符会导致使用特殊方法-到目前为止还不错。 但是,当我运行以下示例时,我得到两个不同的结果。 结果: 现在,据我了解,执行Python时检查/执行int方法-发现没有实现添加int和C对象的实现-返回NotImplemented- 这使Python知道检查对象C并执行其中的代码。 为什么执行代码会导致结果,但是其他

  • 问题内容: 这是我的第一个问题,我开始学习Python。之间有什么区别: 和 在下面的示例中编写时,它显示不同的结果。 和 问题答案: 在中,在将右侧的表达式赋给左侧之前对其求值。因此,它等效于: 在第二个示例中,运行时已更改的值。因此,结果是不同的。