摘要:因而,我們可以得出兩個結論在實例化子類對象時,會執行父類中所有未加載的構造代碼塊和與子類相同的構造器。
導讀
今天在做公司的項目,即統計實例化對象的存活個數,例如以下的代碼
package com.zbystudy; /** * Created By zby on 14:27 2019/4/12 */ public class StaticFiled { public static int count = 0; private final int objCount = count++; public void printObjCount() { System.out.println("生成對象的個數為: " + objCount); } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new StaticFiled().printObjCount(); } } }
輸出如圖所示:
在靜態代碼塊中加法但是,我如果把代碼修改成這樣的:
public class StaticFiled { public static int count = 0; static { count++; } private final int objCount = count; 。。。。。。 }
你會發現,其只輸出1,為什么會這樣呢?會在下文講解。
在構造代碼塊中加法我們再把代碼修改成這樣的,結果又會不一樣:
public class StaticFiled { public static int count = 0; { count++; } private final int objCount = count; 。。。。。。 }
其輸出結果是這樣的:
你會發現,其跳過了0,而直接從1輸出,哈哈,很奇怪,對吧?我也覺著很奇怪,不過,會在下文作詳細介紹。
概念 構造器 概念假想我們沒有構造器,但是我們還需要創建對象。因為,java是通過消息來請求其他對象。要想請求對象,勢必向該對象發送一條消息,換句話說,可以把消息當做某個特定對象的方法的調用。因而,對象還是很重要的。如果我們手動去寫一個方法,即初始化創建對象的方法,這勢必會非常繁瑣的。
因而,我們就想到了java自帶的構造器,其就是為了初始化對象的。
構造代碼塊 概念定義在類的成員位置上,使用"{}"括起來的代碼。構造代碼塊會在每次類被調用,或者被實例化時就會被執行。其優于用以實例化對象的構造器,如代碼所示:
/** * Created By zby on 16:49 2019/4/12 */ public class Child{ private String name; public Child(String name) { super(name); this.name = name; } public Child(){ System.out.println("子類Child類的構造器"); } { System.out.println("子類Child類的 第一個 構造代碼塊"); } { System.out.println("子類Child類的 第二個 構造代碼塊"); } public static void main(String[] args) { new Child(); } }
其輸出結果如圖所示:
你會發現,程序先執行構造代碼塊,然后再執行構造器,也就是說,構造代碼塊的優先級比構造器的優先級高。
這也解決了我們上面的問題,為什么程序的輸出會跳過0,直接從1開始輸出呢?因為,我們首次實例化StaticFiled對象之前,構造代碼塊就已執行了一遍,此時的count是1,而不是0了。
同時,你也會發現,構造代碼塊的執行本身也是有先后順序的,先寫的先輸出,后寫的后輸出。
父類中的構造代碼塊但是,如果父類中有構造代碼塊,子類輸出又是什么樣的呢?這樣,我們定義一個父類,如代碼所示:
public class Parent { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public Parent() { System.out.println("父類Parent類的構造器"); } { System.out.println("父類Parent類的 第一個 構造代碼塊"); } { System.out.println("父類Parent類的 第一個 構造代碼塊"); } }
我們再次執行Child類,觀察此時的輸出結果:
你會神奇的發現,首先輸出父類的構造代碼塊和構造器,再次輸出子類的構造代碼塊和構造器。
因而,我們可以得出兩個結論:
在實例化子類對象時,會執行父類中所有未加載的構造代碼塊和與子類相同的構造器。
與子類相同的構造器是什么意思?也就是說,如果我們把Child類中main方法,修改為這樣的: public static void main(String[] args){new Child("hhhh");},其輸出結果是這樣的:
父級和子類構造代碼塊和構造器之間的優先級:父級構造代碼塊 --》 父級構造器 --》 子類構造代碼塊 --》 子類構造器
靜態代碼塊 概念靜態代碼塊只執行一次,是在某個特定類第一次創建對象的時候執行,此后不再執行該靜態代碼塊,如代碼所示:
/** * Created By zby on 16:49 2019/4/12 */ public class Child extends Parent { private String name; public Child() { // System.out.println("子類Child類的構造器"); } static { System.out.println("子類Child類的靜態代碼塊"); } public static void main(String[] args) { for (int i=0;i<10;i++){ new Child(); } } }
我們創建了10個子類對象,但只輸出一次靜態代碼塊中的數據,結果如圖所示:
這也解決了上面的問題,為什么我們在靜態代碼塊中執行這個指令: static {count++;} ,其輸出結果始終是 1 的原因了。父類靜態代碼塊
但是如果父類中存在靜態代碼塊,子類的輸出又是什么樣的呢?
在Parent類中添加代碼: static {System.out.println("父類Parent類的靜態代碼塊");}
在Child類中添加代碼: static {System.out.println("子類Child類的靜態代碼塊");}
我們執行子類的代碼,得到的截圖:
由上圖,我們得出了結論:
首先執行父類中的靜態代碼塊,再執行子類的靜態代碼塊。三者綜合應用
父類中存在靜態代碼塊、構造代碼塊、構造器,子類中也存在靜態代碼塊、構造代碼塊、構造器,那么,輸出結果是什么樣的呢?
輸出結果如圖說示:
我們得出了這個結論三者的優先級:
父類靜態代碼塊 --》 子類靜態代碼塊 --》父類構造代碼塊 --》 父類的構造器 --》子類構造代碼塊 --》子類構造器總結
我們只有明白了父類靜態代碼塊、子類靜態代碼塊、父類構造代碼塊、父類的構造器、子類構造代碼塊、子類構造器的關系,才能做更多的事情。就像是蓋房子,地基打得越牢固,蓋的房子越穩定。否則,蓋得越高,危險性越大。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77561.html
摘要:構造塊優先于構造函數執行,如果存在多個構造代碼塊,則執行順序按照定義的順序依次執行。靜態代碼塊在中使用關鍵字聲明的代碼塊。同步代碼塊需要寫在方法中。 代碼塊 在java中用{}括起來的稱為代碼塊,代碼塊可分為以下四種: 普通代碼塊 構造代碼塊 靜態代碼塊 同步代碼塊 普通代碼塊 在方法或語句中出現的{}就稱為普通代碼塊。普通代碼塊和一般語句的執行順序由他們在代碼中出現的次序決定,先...
摘要:沒有關鍵字修飾的如實例變量非靜態變量非靜態代碼塊初始化實際上是會被提取到類的構造器中被執行的,但是會比類構造器中的代碼塊優先執行到,非靜態實例變量非靜態代碼塊的地位是相等的,它們將按順序被執行。 閱讀原文:Java代碼執行順序 程序中代碼執行的順序非常重要,稍有不慎便會是程序運行出錯,那么我將結合實例來分析代碼中的執行。 名詞解釋 首先了解幾個名詞: 非靜態代碼塊 直接由 { } 包起...
摘要:代碼塊我們主要觀察普通代碼塊構造塊靜態塊的主要作用。代碼實例構造方法類的構造方法將代碼塊寫在了類里面類的構造塊控制臺輸出類的構造塊類的構造方法此時實例化類對象時,雖然執行的是類的構造方法,但是構造塊里面的代碼也執行了。 代碼塊 我們主要觀察普通代碼塊、構造塊、靜態塊的主要作用。 在程序編寫之中可以直接使用{} 定義一段語句,那么根據此部分定義的位置以及關鍵字的不同可以分為以下幾種: ...
摘要:父類,子類子類方法三者中有同名變量時,調用子類方法輸出,輸出,為子類方法中的值,表示子類中的值,表示父類中的值。靜態代碼塊構造代碼塊構造方法靜態代碼塊構造代碼塊構造方法父類和子類都有靜態代碼塊,構造代碼塊,構造方法,初始化子類對象。 package cat1; class fu{ public int num=10; public fu() { Sy...
這是網易2015校招Java面試題,直接上題目。 題目 package com.mousycoder.staticTest; public class HelloB extends HelloA { public HelloB() { System.out.println(HelloB); } { System.out.println(I...
閱讀 3557·2021-08-02 13:41
閱讀 2391·2019-08-30 15:56
閱讀 1520·2019-08-30 11:17
閱讀 1174·2019-08-29 15:18
閱讀 580·2019-08-29 11:10
閱讀 2671·2019-08-26 13:52
閱讀 508·2019-08-26 13:22
閱讀 2949·2019-08-23 15:41