一个对象从无到有的过程
A a = new A()
1、JVM遇到new指令就会去堆内存分配一块内存空间,内存的大小在编译期间就可以确定
2、接着调用A的构造函数,这里构造的时候会沿着继承树逆流而上,一直到Object。
先看一段代码:
package jvm.test3; public class Sup { public int a;
public String b; Sup(int a, String b){
System.out.println("Sup constructor!!!");
System.out.println(this.getClass().getName());
this.a = a;
this.b = b;
this.printMsg();
} private void printMsg(){
System.out.println("Sup: " + "a=" + a + " b=" + b);
}
} package jvm.test3; public class Sub extends Sup{ Sub(int a, String b) {
super(a, b);
System.out.println("Sub constructor!!!");
} } package jvm.test3; public class Test { public static void main(String[] args) {
new Sub(11,"hello");
} }
输出:
Sup constructor!!!
jvm.test3.Sub
Sup: a=11 b=hello
Sub constructor!!!
这段代码中,我主要想说一下第10行和第13行。
先说说this。在实例方法中,JVM会默认隐藏的传递一个参数,这个参数就是当前调用的实例本身,在方法内就可以通过this操作。
但是等等,在Sup的构造方法中,this却是jvm.test3.Sub类的实例。为什么???
从头再看初始化顺序:new Sub(11,"hello"),new指令会分配一块内存存放Sub对象的数据,然后返回一个引用(假设叫ref)指向这个对象。JVM会去调用Sub的构造方法,并将ref隐藏的传递给构造方法,所以在Sub的构造方法中的this就是ref。但是,Sub的构造方法先去调用父类Sup的构造方法,而JVM这时候隐藏传递进去的还是ref,还是指向Sub实例的引用。
但是又产生一个问题,竟然是Sub的实例,为什么能调用父类Sup的私有方法printMsg???
我想到一种解释:隐藏的参数的类型是本类型。什么意思?就是说在Sup类的所有方法中,隐藏的参数的类型是Sup。所以,当传来一个Sub类的引用ref的时候,进行了一次向上转型。
虽然我觉得非常合理,但是还没有找到验证的方法。大家有懂的或者有其他的想法可以指正。
参考《深入Java虚拟机》