JVM与对象初始化
一个对象从无到有的过程
A a = new A()
1、JVM遇到new指令就会去堆内存分配一块内存空间,内存的大小在编译期间就可以确定
2、接着调用A的构造函数,这里构造的时候会沿着继承树逆流而上,一直到Object。
先看一段代码:
1 package jvm.test3; 2 3 public class Sup { 4 5 public int a; 6 public String b; 7 8 Sup(int a, String b){ 9 System.out.println("Sup constructor!!!"); 10 System.out.println(this.getClass().getName()); 11 this.a = a; 12 this.b = b; 13 this.printMsg(); 14 } 15 16 private void printMsg(){ 17 System.out.println("Sup: " + "a=" + a + " b=" + b); 18 } 19 } 20 21 22 23 package jvm.test3; 24 25 public class Sub extends Sup{ 26 27 Sub(int a, String b) { 28 super(a, b); 29 System.out.println("Sub constructor!!!"); 30 } 31 32 } 33 34 35 36 package jvm.test3; 37 38 public class Test { 39 40 public static void main(String[] args) { 41 new Sub(11,"hello"); 42 } 43 44 }
输出:
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虚拟机》