【问题标题】:why polymorphism in java call the methods from the superclass为什么java中的多态性调用超类中的方法
【发布时间】:2017-01-10 03:49:42
【问题描述】:
///Example code here
Superclass{ 
    method1(){ 
      print(do1);
     }
    method2(){}
  }
Subclass extends Superclass{
   ///override method1
 method1(){ 
      print(do2);
    }
 method3(){}
 }

我对java中的多态性有一个疑问,就是Superclass s =new Subclass()。 “s”对象总是调用超类中的方法,但是当覆盖方法发生时,“s”将指向覆盖方法。

更新: 所以,问题是谁来为引用“s”创建一个堆地址,如果它最终可以编译和运行。如果超类创建了它,为什么是 new Subclass() 而不是 new Superclass()。如果子类创建了它,为什么不能使用 s.method3()。

【问题讨论】:

  • 真的不清楚你在这里问什么。您能否提供一个不符合您预期的minimal reproducible example? (除此之外,我会忽略任何堆栈/堆的区别——专注于“引用”与“对象”和“编译时类型”与“执行时类型”。这些与讨论更相关。)
  • @fabian,当然,s 被声明为超类,但堆地址是为子类创建的,对吧?并且“s”指向 HEAP
  • @JonSkeet,这让我很困惑,因为我一直认为 new Object() 实际上在堆中创建了一个新地址,所以无论如何引用都应该指向真实地址
  • 再一次,您将注意力集中在堆栈与堆上,而没有明确解释什么让您感到困惑。
  • s 在运行时指向什么并不重要。 编译器 不允许您在Superclass 类型的表达式上调用method3。这发生在使用该代码的程序中存在堆栈/堆之前。您可以通过强制转换访问s 中的method3,但如果该对象实际上不是SubclassSubclass 子类,您将在运行时获得ClassCastException((Subclass) s).method3()

标签: java polymorphism overriding heap-memory stack-memory


【解决方案1】:

s 可以调用method3。你只需要先施放它。如果他们允许 s 将 method3 作为超类调用,那就没有意义了,因为并非所有超类都可以调用 method3。

【讨论】:

    【解决方案2】:

    方法的动态绑定将在运行时决定,因此首先当您调用以 s 作为其引用的方法时,超类编译器将始终首先检查超类是否具有该方法。有2个案例

    1. 如果超类有方法,JVM 会继续检查子类,如果子类有覆盖方法,则调用该方法,如果子类没有该方法比通常父类方法会调用。

    2.如果超类没有该方法,则编译失败,因为编译器无法识别引用变量类中的任何方法

    所以在你的情况下,如果超类没有method3,那么它会挑衅地给出编译错误

    【讨论】:

    • 同样,这个“s”引用是由Superclass创建的,它只是STACK中的一个引用。 JVM 将继续检查真实地址以检查哪个是 HEAP。但是这里的 HEAP 是 Subclass,JVM 是如何知道 HEAP 中 Superclass 的地址的呢?我认为当时的超类没有物理地址
    • JVM 只有在编译成功并且这个父类必须有那个方法时才会继续,因为编译器不知道在运行时会发生什么,甚至我们也不应该总是忘记那个子类继承父类的属性,所以如果孩子没有方法,它将调用父方法
    • @Field.D 这与内存分配无关。在大多数情况下,您甚至不必担心 Java 中的内存分配,因为这是由 JVM 处理的。这种行为是有意的,也是语言的重要组成部分。
    • 在第 1 点中,您的意思是 覆盖。任何 overload 解析都是在编译时执行的。区分重载和覆盖很重要。
    • 感谢 Jon 更正,这是我这边常见的错字:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    相关资源
    最近更新 更多