让我们先来看两个类:Base和Derived类。注意其中的whenAmISet成员变量,和方法preProcess()。
情景1:(子类无构造方法)
class Base { Base() { preProcess(); } void preProcess() { } } class Derived extends Base { public String whenAmISet = "set when declared"; void preProcess() { whenAmISet = "set in preProcess()"; } } public class StaticTest { public static void main(String[] args) { Derived d = new Derived(); System.out.println(d.whenAmISet); } }
当.java源代码转换成一个.class文件后,其转换成类似下面的等价代码:
class Base { Base() { preProcess(); } void preProcess() { } } class Derived extends Base { public String whenAmISet; {whenAmISet = "set when declared";} void preProcess() { whenAmISet = "set in preProcess()"; } } public class StaticTest { public static void main(String[] args) { Derived d = new Derived(); System.out.println(d.whenAmISet); } }
输出结果是: set when declared
情景2:(子类添加了构造方法)
class Base { Base() { preProcess(); } void preProcess() { } } class Derived extends Base { public String whenAmISet = "set when declared"; public Derived() { whenAmISet = "set in constructor"; } void preProcess() { whenAmISet = "set in preProcess()"; } } public class StaticTest { public static void main(String[] args) { Derived d = new Derived(); System.out.println(d.whenAmISet); } }
当.java源代码转换成一个.class文件后,其转换成类似下面的等价代码:
class Base { Base() { preProcess(); } void preProcess() { } } class Derived extends Base { public String whenAmISet; public Derived() { whenAmISet = "set when declared"; whenAmISet = "set in constructor"; } void preProcess() { whenAmISet = "set in preProcess()"; } } public class StaticTest { public static void main(String[] args) { Derived d = new Derived(); System.out.println(d.whenAmISet); } }
输出结果为:set in constructor
情景3:(赋值的细节)
public class Singleton { private static Singleton mInstance = new Singleton(); // 位置1 public static int counter1; public static int counter2 = 0; private Singleton() { counter1++; counter2++; } public static Singleton getInstantce() { return mInstance; } public static void main(String[] args) { Singleton singleton = Singleton.getInstantce(); System.out.println("counter1: " + singleton.counter1); System.out.println("counter2: " + singleton.counter2); } }
当.java源代码转换成一个.class文件后,其转换成类似下面的等价代码:
public class Singleton { private static Singleton mInstance; public static int counter1; public static int counter2; static { mInstance = new Singleton(); counter2 = 0; } private Singleton() { counter1++; counter2++; } public static Singleton getInstantce() { return mInstance; } public static void main(String[] args) { Singleton singleton = Singleton.getInstantce(); System.out.println("counter1: " + singleton.counter1); System.out.println("counter2: " + singleton.counter2); } }
- 在Prepare阶段,mInstance、counter1、counter2的初始值为(null,0,0);
- 执行至 mInstance = new Singleton()时,进行实例创建并调用构造方法,使counter1、counter2变量的值改变为(1,1);
- 执行counter2 = 0时,counter2的值再次置为0,最终程序的输出结果为:counter1: 1 counter2: 0
同理,以下代码的最终输出结果为:counter1: 1 counter2: 1
public class Singleton { public static int counter1; public static int counter2 = 0; private static Singleton mInstance = new Singleton(); // 位置2 private Singleton() { counter1++; counter2++; } public static Singleton getInstantce() { return mInstance; } public static void main(String[] args) { Singleton singleton = Singleton.getInstantce(); System.out.println("counter1: " + singleton.counter1); System.out.println("counter2: " + singleton.counter2); } }
原因分析:
- 陈皓博客
- Java Tutor - Visualize Java code execution to learn Java online (also visualize Python, Java, JavaScript, TypeScript, Ruby, C, and C++ code)