最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中對象初始化順序的詳細(xì)介紹

 更新時間:2016年10月04日 08:50:36   投稿:daisy  
在Java中,類裝載器把一個類裝入Java虛擬機中,要經(jīng)過三個步驟來完成:裝載、鏈接和初始化,網(wǎng)上關(guān)于Java中對象初始化順序的文章很多,這篇文章我們將詳細(xì)介紹Java中對象初始化順序。有需要的可以參考學(xué)習(xí)。

前言

在Java中,一個對象在可以被使用之前必須要被正確地初始化,這一點是Java規(guī)范規(guī)定的。最近我發(fā)現(xiàn)了一個有趣的問題,這個問題的答案乍一看下騙過了我的眼睛??匆幌逻@三個類:

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";
 }
}

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

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

Upper: upperInited
Lower: null;

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

現(xiàn)在稍微改變一下 Lower 的代碼:

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();
 }
}

現(xiàn)在的輸出是這樣的:

Upper: upperInited
Lower: lowerInited

發(fā)現(xiàn)代碼中的區(qū)別了嗎?

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

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

1.main() 函數(shù)調(diào)用了 Lower 構(gòu)造器。

2.Lower 的一個實例被準(zhǔn)備好了。意味著所有的字段都被創(chuàng)建并且填充了默認(rèn)值,例如,引用類型的默認(rèn)值為空,布爾類型的默認(rèn)值為 false 。在這個時候,任何的對字段的內(nèi)聯(lián)賦值都沒有發(fā)生。

3.父類構(gòu)造器被調(diào)用了。這是被語言的特性所強制執(zhí)行的。所以在其他任何事發(fā)生之前,Upper 的構(gòu)造器被調(diào)用了。

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

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

6.Initializer.initialize() 的調(diào)用完成,Upper 構(gòu)造器也同樣完成。

7.現(xiàn)在變得有趣了:Lower 實例的構(gòu)造在繼續(xù)。假設(shè)在 lowerString 字段的聲明中沒有明確地 =null 賦值,Lower 構(gòu)造器恢復(fù)執(zhí)行并且打印出兩個連接到字段的字符串。

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

這是一個很好的例子,不僅方便我們?nèi)绾巫⒁庖恍﹦?chuàng)建對象的細(xì)節(jié)(或者知道去哪里查看 Java 編碼規(guī)范,打印的或者在線的),還顯示了為什么像這樣寫初始化是很糟糕的。我們一點都不應(yīng)該關(guān)心 Upper 的子類。相反的,如果因為一些原因?qū)δ承┳侄蔚某跏蓟荒茉谧宇惐旧肀煌瓿?,它將只需要它自己的某些初始化幫助類的變體。在這種情況下,如果你使用 String lowString 或者 String lowerString = null 是真的沒有任何區(qū)別的,它應(yīng)該是什么就會是什么。

總結(jié)

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

相關(guān)文章

最新評論

高碑店市| 兰州市| 潍坊市| 酒泉市| 明光市| 海晏县| 新宁县| 桦南县| 满洲里市| 内丘县| 泽普县| 明水县| 安塞县| 新野县| 和田市| 武清区| 株洲县| 永川市| 固始县| 明溪县| 屏南县| 天镇县| 吐鲁番市| 大港区| 吉首市| 黄平县| 丰顺县| 弋阳县| 杭州市| 南昌县| 石景山区| 喀喇沁旗| 越西县| 嘉鱼县| 无极县| 河源市| 宽甸| 华坪县| 韶关市| 马边| 高青县|