一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java中對象初始化順序的詳細介紹

Java中對象初始化順序的詳細介紹

2020-06-20 12:38daisy JAVA教程

在Java中,類裝載器把一個類裝入Java虛擬機中,要經過三個步驟來完成:裝載、鏈接和初始化,網上關于Java中對象初始化順序的文章很多,這篇文章我們將詳細介紹Java中對象初始化順序。有需要的可以參考學習。

前言

Java中,一個對象在可以被使用之前必須要被正確地初始化,這一點是Java規范規定的。最近我發現了一個有趣的問題,這個問題的答案乍一看下騙過了我的眼睛。看一下這三個類:

?
1
2
3
4
5
6
7
8
9
package com.ds.test;
 
public class Upper {
 String upperString;
 
 public Upper() {
 Initializer.initialize(this);
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();
 }
}
?
1
2
3
4
5
6
7
8
9
10
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";
 }
}

運行 Lower 這個類可以得到什么輸出?在這個極簡的例子中可以更容易地看到整個形勢,但是這個情形發生在現實中會有非常多的代碼分散一個人的注意力。

不管怎么樣,輸出是像這樣的:

?
1
2
Upper: upperInited
Lower: null;

雖然小示例中使用了 String 類型,Initializer 類的實際代碼中有一個用于注冊的委托對象,與 Lower 類的功能是相同的 — 至少 Lower 類是這個意圖。但由于某些原因在運行應用程序時沒有工作。取而代之的是,使用了默認路徑,委托對象沒有被設置 (null)。

現在稍微改變一下 Lower 的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();
 }
}

現在的輸出是這樣的:

?
1
2
Upper: upperInited
Lower: lowerInited

發現代碼中的區別了嗎?

是的,這個 lowerString 字段不再明確地設置為空。為什么這么做會有不同。不管怎樣參考類型字段(例如這里的 String )的默認值不是為空的嗎?當然是空的。事實證明,雖然這種微小的變化顯然不會以任何方式改變代碼行為,但是卻讓結果變的不同。

那么,到底發生了什么?當查看初始化順序的時候一切就變的清晰了:

1.main() 函數調用了 Lower 構造器。

2.Lower 的一個實例被準備好了。意味著所有的字段都被創建并且填充了默認值,例如,引用類型的默認值為空,布爾類型的默認值為 false 。在這個時候,任何的對字段的內聯賦值都沒有發生。

3.父類構造器被調用了。這是被語言的特性所強制執行的。所以在其他任何事發生之前,Upper 的構造器被調用了。

4.Upper 這個構造器運行并且指定了一個引用,指向 Initializer.initialize() 方法新創建的的實例。

5.Initializer 類為兩個字段( upperString lowerString )附上新字符串。通過使用有點骯臟的 instanceof 實例檢查做到為那兩個字段賦值 – 這不是一個特別好的 設計模式 ,但是也有可行的,不用管那么多。一旦發生了,upperString lowerString 的引用都不再為空。

6.Initializer.initialize() 的調用完成,Upper 構造器也同樣完成。

7.現在變得有趣了:Lower 實例的構造在繼續。假設在 lowerString 字段的聲明中沒有明確地 =null 賦值,Lower 構造器恢復執行并且打印出兩個連接到字段的字符串。

然而,如果有一個明確地賦值 null 的操作,執行流程會略有不同:當父類構造器完成后,在其余的構造器運行前,任何變量初始化都會執行(參見java語言規范12.5節)。在這種情況下,之前賦值給 lowerString 的字符串引用不會再一次被賦予 null 。然后繼續執行其余的函數構造,現在打印 lowerString 的值為: null 。

這是一個很好的例子,不僅方便我們如何注意一些創建對象的細節(或者知道去哪里查看 Java 編碼規范,打印的或者在線的),還顯示了為什么像這樣寫初始化是很糟糕的。我們一點都不應該關心 Upper 的子類。相反的,如果因為一些原因對某些字段的初始化不能在子類本身被完成,它將只需要它自己的某些初始化幫助類的變體。在這種情況下,如果你使用 String lowString 或者 String lowerString = null 是真的沒有任何區別的,它應該是什么就會是什么。

總結

以上就是這篇文章的全部內容了,希望這篇文章的內容對大家的學習或者工作能帶來一定的幫助,如果有問題大家可以留言交流。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 2019nv天堂香蕉在线观看 | 精品一区二区三区免费视频 | 欧美日本一区视频免费 | 亚洲第一永久色 | 大伊香蕉精品视频一区 | 成年人在线观看视频 | 五月九九 | 继攵催眠女乱h调教 | 娇妻被又大又粗又长又硬好爽 | 我将她侵犯1~6樱花动漫在线看 | 国产亚洲精品线观看77 | 污小说h | 99久久精品无码一区二区毛片 | 非洲特级特黄aa大片 | 国产色视频一区二区三区 | 性插图动态图无遮挡 | 色五月天天| 国精品午夜dy8888狼人 | 五月丁开婷婷 | 成人精品视频 成人影院 | 欧美粗黑巨大gay | 亚洲欧美日韩另类在线 | 日韩成人在线影院 | 亚洲国产成人久久综合一区77 | 息与子中文字幕在线 | 久久久精品日本一区二区三区 | 色噜噜国产精品视频一区二区 | 国产一区二区不卡 | 国产美女下面流出白浆视频 | bbc japanese黑人强行 | 91久操 | 亚洲第一区在线观看 | 久久精品视频免费 | 色偷偷亚洲综合网亚洲 | 九九99亚洲精品久久久久 | 成人性爱视频在线观看 | 天天色国产 | h日本漫画全彩在线观看 | 天天干天天爽天天操 | 办公室的秘密在线观看 | 激情视频网址 |