继承和内存分配

Inheritance and memory allocation

对于以下代码:

class Parent {
    public void say(){
        System.out.println("Parent");
    }
}

class Child extends Parent{
    public void say(){
        System.out.println("Parent");
    }
}

class Test {
    public static void main(String[] args){

        Parent p = new Child(); // What does the compiler check  
        p.say();
    }
}

下面的问题一直困扰着我

1.编译期间到底发生了什么?编译器如何知道 Parent p = new Child() 是有效代码,因为在编译时没有创建对象?

2。运行时到底发生了什么?内存是怎么分配的

3。对父构造函数的隐式调用创建了一个父对象。还创建了一个子对象。它是如何存储的以及jvm如何使用它来进行方法解析。

4.最后,JVM 是否被硬编码为不覆盖静态方法和变量,或者还有其他一些原因。为什么我们不能使用运行时对象实例方法() 为什么不能使用运行时对象变量

在哪里可以阅读有关这些主题的更多信息?

谢谢

exactly is happening during compile time? How does the comiler know that Parent p = new Child() is a valid code as no object has been created at compile time?

好吧,整本书都是关于这个主题的。本质上,编译器解析输入源,发现赋值:

Parent p = new Child(); 

现在编译器做了两件事:

  • 它检查它能找到关于赋值
  • 两边的类型的内容
  • 因此它发现:左侧需要一个`Parent``类型的对象
  • 它还会查看右侧,以了解该表达式的(潜在)结果类型

所以,最后,编译器会看到:"I need a Parent ... and I get something that is a Child." 然后编译器必须检查 Child 的实例是否满足 "I need a Parent"。显然:确实如此。

what exactly is happening at runtime? How is memory allocated

同样,整本书都是关于这个的。例如,参见 here

The implicit call to parent's constructor creates an Parent Object. A child object is also created. How is it stored and how does jvm use this for method resolution.

JVM "simply" 知道两件事:

  • 为子对象保留内存时,需要考虑任何超级class字段所需的内存
  • 所以,最后,您只需要一个足够大的内存区域来容纳所有父 class 的所有字段,一直到子 class 本身

最后:静态方法是固有的,但是,Java 中它们没有多态性。这只是语言的一个设计点,以及为 Java 定义的语义。它可以以不同的方式完成,但 20 多年前,Java 的父亲们决定像他们那样做。