对于以下代码:
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进行了硬编码,以使其不能够覆盖静态方法和变量,或者还有其他原因。为什么我们不能使用运行时对象实例method()为什么不使用运行时对象变量
在哪里可以阅读有关这些主题的更多信息?
谢谢
答案 0 :(得分:2)
是在编译期间发生的吗?编译器如何知道Parent p = new Child()是有效的代码,因为在编译时尚未创建任何对象?
好吧,整本书都是关于这个主题的。本质上,编译器解析输入源,并找到该分配:
Parent p = new Child();
现在,编译器执行两件事:
因此,最后,编译器将看到:“我需要一个父级...并且我得到的是子级。”然后,编译器必须检查Child的实例是否满足“我需要父母”。显然:是的。
运行时到底发生了什么?如何分配内存
同样,整本书都写了。例如,请参见here。
对父级构造函数的隐式调用将创建一个父级对象。还将创建一个子对象。它的存储方式以及jvm如何将其用于方法解析。
JVM“简单地”知道两件事:
最后:静态方法是固有的,但是是的,在Java中它们没有多态性。那只是语言的设计点,以及为Java定义的语义。可以用不同的方式来做,但是20多年前,Java的父亲决定像他们一样做。