Java 对象初始化过程
生活随笔
收集整理的這篇文章主要介紹了
Java 对象初始化过程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
例子里總共測試了靜態代碼塊,普通代碼塊,靜態成員變量,普通成員 變量,構造器。分別在基類和派生類里各有一套。
public class ClassLog {private static final String TAG = "ClassLog";public static String baseFieldInit() {Loger.i(TAG, "baseFieldInit");return "";}public static String baseStaticFieldInit() {Loger.i(TAG, "baseStaticFieldInit");return "";}public static String childFieldInit() {Loger.i(TAG, "childFieldInit");return "";}public static String childStaticFieldInit() {Loger.i(TAG, "childStaticFieldInit");return "";} } public class ClassBase {private static final String TAG = "ClassBase";static {System.out.println("Base Static Block 1");}private static String BASE_STATIC_VALUE = ClassLog.baseStaticFieldInit();static {Loger.i(TAG, "Base Static Block 2");}{Loger.i(TAG, "Base Normal Block 1");}private String baseNormalValue = ClassLog.baseFieldInit();{Loger.i(TAG, "Base Normal Block 2");}public ClassBase() {Loger.i(TAG, "Base Class Constructor");} }
public class ClassChild extends ClassBase {private static final String TAG = "ClassChild";static {Loger.i(TAG, "Child Static Block 1");}private static String CHILD_STATIC_VALUE = ClassLog.childStaticFieldInit();static {Loger.i(TAG, "Child Static Block 2");}{Loger.i(TAG, "Child Normal Block 1");}private String childNormalValue = ClassLog.childFieldInit();{Loger.i(TAG, "Child Normal Block 2");}public ClassChild() {Loger.i(TAG, "Child Class Constructor");} }
創建一個ClassChild類的對象:
ClassChild tChild = new ClassChild();
Log 如下:
結果證明:
對象在class文件加載完畢,以及為各成員在方法區開辟好內存空間后,就開始了所謂“初始化”的過程:
1.基類靜態代碼塊、基類靜態成員字段(并列優先級,按代碼中出現的先后順序)(只有第一次加載類時執行);
2.派生類靜態代碼塊、基類靜態成員字段(并列優先級,按代碼中出現的先后順序)(只有第一次加載類時執行);
3.基類普通代碼塊、基類普通成員字段(并列優先級,按代碼中出現的先后順序);
4.基類構造函數;
5.派生類普通代碼塊、基類普通成員字段(并列優先級,按代碼中出現的先后順序);
6.派生類構造函數;
注意: 第1、第2步驟的靜態過程,只在這個類第一次被加載的時候才會運行。
再創建一個ClassChild類的對象:
ClassChild tChild = new ClassChild();
第二次創建只執行3、4、5,6步。
From:https://www.zhihu.com/question/49196023
Java Object Initialization Order - Know your JLS!
Recently I came across an interesting problem whose solution eluded me at first glance. Consider these three classes:package com.ds.test;public class Upper {String upperString;public Upper() {Initializer.initialize(this);} } package com.ds.test;public class Lower extends Upper {String lowerString = null;public Lower() {super();System.out.println("Upper: " + upperString);System.out.println("Lower: " + lowerString);}public static void main(final String[] args) {new Lower();} } package com.ds.test; public class Initializer {static void initialize(final Upper anUpper) {if (anUpper instanceof Lower) {Lower lower = (Lower) anUpper;lower.lowerString = "lowerInited";}anUpper.upperString = "upperInited";} } What output is to be expected from running the?Lower?class?
In this very reduced example it is much easier to get a view of the whole situation - in reality where this occurred there was a lot more code to distract one's attention...
Anyway, this is what the output looks like:
Upper: upperInited Lower: null; While the little example uses Strings, the real code of?Initializer?had a delegate object registered with the equivalent of the?Lower?class - at least that was the intention. For some reason however did this not work when running the application. Instead, the default path was taken - the one for the delegate object being not set (null).
Now, change the code of?Lower?slightly:
package com.ds.test;public class Lower extends Upper {String lowerString;public Lower() {super();System.out.println("Upper: " + upperString);System.out.println("Lower: " + lowerString);}public static void main(final String[] args) {new Lower();} } The output is now:
Upper: upperInited Lower: lowerInited Notice the difference in the code?
Yes, the?lowerString?field is no longer explicitly set to?null. Why would this make a difference? Isn't the default value for reference type fields (such as?String?here)?null?anyway? Of course, it is. However it turns out that this tiny little change - which apparently would not change the code's behavior in any way - makes this thing fly or not fly.
So what is going on? It becomes clear when looking at the initialization order:
However, if there?is?an explicit assignment to?null, execution has a slightly different flow: Just after the super constructor is done, any variable initializers are executed (see?section 12.5 of the Java Language Spec),?before?the rest of the constructor is run. In this case the?String?reference that was previously assigned to?lowerString?is now overwritten with?null?again! Only then does the rest of the constructor continue execution, now printing?lowerString: null.
From:http://www.danielschneller.com/2010/07/java-object-initialization-order-know.html
總結
以上是生活随笔為你收集整理的Java 对象初始化过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从fragment开始向上查找实现了某个
- 下一篇: Java PECS