Java靜態代碼塊 靜態方法 構造代碼塊 普通方法


Java中靜態代碼塊、構造代碼塊、構造函數、普通代碼塊

  

  在Java中,靜態代碼塊、構造代碼塊、構造函數、普通代碼塊的執行順序,希望大家多能記住。


1、靜態代碼塊

  ①、格式

  在java類中(方法中不能存在靜態代碼塊)使用static關鍵字和{}聲明的代碼塊:

1
2
3
4
5
public  class  CodeBlock {
     static {
         System.out.println( "靜態代碼塊" );
     }
}

  ②、執行時機

  靜態代碼塊在類被加載的時候就運行了,而且只運行一次,並且優先於各種代碼塊以及構造函數。如果一個類中有多個靜態代碼塊,會按照書寫順序依次執行。后面在比較的時候會通過具體實例來證明。

  ③、靜態代碼塊的作用

  一般情況下,如果有些代碼需要在項目啟動的時候就執行,這時候就需要靜態代碼塊。比如一個項目啟動需要加載的很多配置文件等資源,我們就可以都放入靜態代碼塊中。

  ④、靜態代碼塊不能存在任何方法體中

  這個應該很好理解,首先我們要明確靜態代碼塊是在類加載的時候就要運行了。我們分情況討論:

  對於普通方法,由於普通方法是通過加載類,然后new出實例化對象,通過對象才能運行這個方法,而靜態代碼塊只需要加載類之后就能運行了。

  對於靜態方法,在類加載的時候,靜態方法也已經加載了,但是我們必須要通過類名或者對象名才能訪問,也就是說相比於靜態代碼塊,靜態代碼塊是主動運行的,而靜態方法是被動運行的。

  不管是哪種方法,我們需要明確靜態代碼塊的存在在類加載的時候就自動運行了,而放在不管是普通方法還是靜態方法中,都是不能自動運行的。

  ⑤、靜態代碼塊不能訪問普通變量

  這個理解思維同上,普通變量只能通過對象來調用,是不能放在靜態代碼塊中的。


2、構造代碼塊

  ①、格式

  在java類中使用{}聲明的代碼塊(和靜態代碼塊的區別是少了static關鍵字):

1
2
3
4
5
6
7
8
public  class  CodeBlock {
     static {
         System.out.println( "靜態代碼塊" );
     }
     {
         System.out.println( "構造代碼塊" );
     }
}

  ②、執行時機

  構造代碼塊在創建對象時被調用,每次創建對象都會調用一次,但是優先於構造函數執行。需要注意的是,聽名字我們就知道,構造代碼塊不是優先於構造函數執行,而是依托於構造函數,也就是說,如果你不實例化對象,構造代碼塊是不會執行的。怎么理解呢?我們看看下面這段代碼:

1
2
3
4
5
6
7
8
9
10
11
12
public  class  CodeBlock {
     {
         System.out.println( "構造代碼塊" );
     }
     
     public  CodeBlock(){
         System.out.println( "無參構造函數" );
     }
     public  CodeBlock(String str){
         System.out.println( "有參構造函數" );
     }
}

  我們反編譯生成的class文件:

  

  如果存在多個構造代碼塊,則執行順序按照書寫順序依次執行。

  ③、構造代碼塊的作用

   和構造函數的作用類似,都能對對象進行初始化,並且只要創建一個對象,構造代碼塊都會執行一次。但是反過來,構造函數則不一定每個對象建立時都執行(多個構造函數情況下,建立對象時傳入的參數不同則初始化使用對應的構造函數)。

  利用每次創建對象的時候都會提前調用一次構造代碼塊特性,我們可以做諸如統計創建對象的次數等功能。


3、構造函數 

  1.構造函數的命名必須和類名完全相同。在java中普通函數可以和構造函數同名,但是必須帶有返回值;

  2.構造函數的功能主要用於在類的對象創建時定義初始化的狀態。它沒有返回值,也不能用void來修飾。這就保證了它不僅什么也不用自動返回,而且根本不能有任何選擇。而其他方法都有返回值,即使是void返回值。盡管方法體本身不會自動返回什么,但仍然可以讓它返回一些東西,而這些東西可能是不安全的;

  3.構造函數不能被直接調用,必須通過new運算符在創建對象時才會自動調用;而一般的方法是在程序執行到它的時候被調用的;

  4.當定義一個類的時候,通常情況下都會顯示該類的構造函數,並在函數中指定初始化的工作也可省略,不過Java編譯器會提供一個默認的構造函數.此默認構造函數是不帶參數的。而一般的方法不存在這一特點;


4、普通代碼塊

  普通代碼塊和構造代碼塊的區別是,構造代碼塊是在類中定義的,而普通代碼塊是在方法體中定義的。且普通代碼塊的執行順序和書寫順序一致。

1
2
3
4
5
public  void  sayHello(){
     {
         System.out.println( "普通代碼塊" );
     }
}

5、執行順序

  •  靜態代碼塊>構造代碼塊>構造函數>普通代碼塊 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public  class  CodeBlock {
     static {
         System.out.println( "靜態代碼塊" );
     }
     {
         System.out.println( "構造代碼塊" );
     }
     public  CodeBlock(){
         System.out.println( "無參構造函數" );
     }
     
     public  void  sayHello(){
         {
             System.out.println( "普通代碼塊" );
         }
     }
     
     public  static  void  main(String[] args) {
         System.out.println( "執行了main方法" );
         
         new  CodeBlock().sayHello();;
         System.out.println( "---------------" );
         new  CodeBlock().sayHello();;
     }
}

  反編譯生成的class文件:

  

 

  執行結果:

   

  我們創建了兩個匿名對象,但是靜態代碼塊只是調用了一次。


6、父類和子類執行順序

  對象的初始化順序:

  首先執行父類靜態的內容,父類靜態的內容執行完畢后,接着去執行子類的靜態的內容,當子類的靜態內容執行完畢之后,再去看父類有沒有構造代碼塊,如果有就執行父類的構造代碼塊,父類的構造代碼塊執行完畢,接着執行父類的構造方法;父類的構造方法執行完畢之后,它接着去看子類有沒有構造代碼塊,如果有就執行子類的構造代碼塊。子類的構造代碼塊執行完畢再去執行子類的構造方法。

  總之一句話,靜態代碼塊內容先執行,接着執行父類構造代碼塊和構造方法,然后執行子類構造代碼塊和構造方法。

  父類:SuperClass.java


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM