1. 程式人生 > >靜態程式碼塊與靜態變數的執行順序

靜態程式碼塊與靜態變數的執行順序

在工具類中,通常會初始化一些單例變數,這些變數由於只會初始一次,並不適合放在建構函式中,因此通常選擇在靜態程式碼塊中執行,那麼在一個類中,就會涉及到靜態變數和靜態程式碼塊的初始化執行順序問題。

  1. public class Test

  2. {

  3. private static Test t = new Test();

  4. private static String a = "1";

  5. static

  6. {

  7. System.out.println(Test.a);

  8. Test.a = "2";

  9. System.out.println(Test.a);

  10. System.out.println(Test.b);

  11. Test.b = "4";

  12. System.out.println(Test.b);

  13. }

  14. private static String b = "3";

  15. private Test()

  16. {

  17. System.out.println("Constructor");

  18. System.out.println(Test.a);

  19. System.out.println(Test.b);

  20. }

  21. public static void start()

  22. {

  23. }

  24. public static void main(String[] args)

  25. {

  26. Test.start();

  27. }

  28. }

上面的程式碼示例中,定義了3 個靜態變數和一個靜態程式碼塊。執行輸出如下:

根據輸出顯示:

首先呼叫建構函式Test() 初始化t,此時列印a,b的值為null,說明此時,a,b還未被初始化賦值。

列印結果1說明在執行完建構函式之後,a被初始化為1。改變a值為2,當列印a時,輸出2.

接著列印b,卻發現輸出為null,說明此時b還未被初始化。

給b賦值為4,列印結果輸出4.

那麼b 在什麼時候初始化呢,其實是在執行完第二個system.out.println(b)時,就開始初始化b為3.

可以增加第二塊靜態程式碼塊進行驗證:

  1. public class Test

  2. {

  3. private static Test t = new Test();

  4. private static String a = "1";

  5. static

  6. {

  7. System.out.println(Test.a);

  8. Test.a = "2";

  9. System.out.println(Test.a);

  10. System.out.println(Test.b);

  11. Test.b = "4";

  12. System.out.println(Test.b);

  13. }

  14. private static String b = "3";

  15. static

  16. {

  17. System.out.println(Test.b);

  18. }

  19. private Test()

  20. {

  21. System.out.println("Constructor");

  22. System.out.println(Test.a);

  23. System.out.println(Test.b);

  24. }

  25. public static void start()

  26. {

  27. }

  28. public static void main(String[] args)

  29. {

  30. Test.start();

  31. }

  32. }

輸出結果為

在private static String b = "3" 之後增加第二塊程式碼塊之後,列印b值為3,說明b在執行完第二個system.out.println(b)時,被賦值b為3.

由此可見,靜態程式碼塊會根據靜態變數的宣告順序及靜態程式碼塊中自身的程式碼順序初始化靜態變數。

上述程式碼等價於下面程式碼:

  1. public class Test

  2. {

  3. private static Test t ;

  4. private static String a;

  5. static

  6. {

  7. Test.t = new Test();

  8. Test.a = "1";

  9. System.out.println(Test.a);

  10. Test.a = "2";

  11. System.out.println(Test.a);

  12. System.out.println(Test.b);

  13. Test.b = "4";

  14. System.out.println(Test.b);

  15. Test.b = "3";

  16. }

  17. private static String b;

  18. static

  19. {

  20. System.out.println(Test.b);

  21. }

  22. private Test()

  23. {

  24. System.out.println("Constructor");

  25. System.out.println(Test.a);

  26. System.out.println(Test.b);

  27. }

  28. public static void start()

  29. {

  30. }

  31. public static void main(String[] args)

  32. {

  33. Test.start();

  34. }

  35. }

實際上,jvm就是按照上述靜態程式碼塊中的順序初始化靜態變數的。

可以執行 javap -c Test檢視Test的位元組碼:


 

為了簡化不必要的指令,刪除了所有的列印語句及第二次程式碼中的追加的靜態程式碼塊。從位元組碼中我們看到,在靜態程式碼塊中,首先執行初始化方法,並初始化t。然後依次從常量池中讀取字串常量初始化a,b。

相關推薦

靜態程式碼靜態變數執行順序

在工具類中,通常會初始化一些單例變數,這些變數由於只會初始一次,並不適合放在建構函式中,因此通常選擇在靜態程式碼塊中執行,那麼在一個類中,就會涉及到靜態變數和靜態程式碼塊的初始化執行順序問題。 public class Test { priv

java中靜態變數靜態方法,靜態程式碼,構造程式碼,構造方法...執行順序

public class TestExeOrder { public TestExeOrder(){ System.out.println("類的構造方法執行了..."); } { System.out.println("構造程式碼塊執行了

JAVA父類子類靜態程式碼靜態變數、構造方法的執行順序

1、第一個檔案Print.java public class Print {    public Print(String s){        System.out.print(s + " ");    }} 2、第二個檔案Test1.java public 

父類子類的靜態程式碼程式碼、構造方法執行順序

StaticTest.java package com.staticTest; /** * 測試靜態程式碼塊執行順序 * 1、static能修飾的類只有靜態內部類 * 2、靜態方法不能直接訪問非

java中靜態變數靜態程式碼靜態方法,例項變數,匿名程式碼的載入順序

1. java中靜態變數,靜態程式碼塊,靜態方法,例項變數,匿名程式碼塊 在Java中,使用{}括起來的程式碼稱為程式碼塊,程式碼塊可以分為以下四種: (1)普通程式碼塊:就是類中方法的方法體 public void xxx(){ //code }

“全棧2019”Java第四十二章:靜態程式碼初始化順序

難度 初級 學習時間 10分鐘 適合人群 零基礎 開發語言 Java 開發環境 JDK v11 IntelliJ IDEA v2018.3 文章原文連結 “全棧2019”Java第四十二章:靜態程式碼塊與初始化順序 下一章 “全棧2019”Java第四十三章:封裝 學

java中四種許可權修飾符,靜態程式碼,構造程式碼,構造方法執行順序

一、java中類有四種許可權 1、要想僅能在本類中訪問使用private修飾。 2、要想本包中的類都可以訪問不加修飾符即可。 3、要想本包中的類與其他包中的子類可以訪問使用protected修飾。(不在同一包中時,只能在子類裡面可以呼叫,其他測試類建物件都不行,只給不同包中的子

Java靜態程式碼程式碼及建構函式執行順序

根據以下程式進行分析 定義一個父類 package sas.LearnJava; public class ExcuteOrderTest { { System.out.println("我是在父類開始的普通程式碼塊!"); } public ExcuteOrder

unity 靜態程式碼和構造方法執行時機和次數

using UnityEngine; using System.Collections; public class test : MonoBehaviour { void Start () { person p01 = new person(); person p

Java基礎篇——靜態程式碼靜態方法、靜態變數、構造方法、構造程式碼段相關

基本定義 靜態程式碼段 在Java類的設計中,如果某段程式碼想讓其只執行一次,比如一個HashMap的生成,一個數據庫連線池的產生,就可以把相關程式碼寫入static{}包裹的程式碼段中。這個程式碼段就叫靜態程式碼段,在專案啟動時就主動執行,即由虛擬機器內部完成呼叫,且只執

靜態程式碼靜態程式碼的區別(Java)

    靜態程式碼塊是以static修飾的程式碼塊,反之沒有用static修飾的程式碼塊為非靜態程式碼塊,如下所示: 靜態程式碼塊: static{ 若干程式碼 } 非靜態程式碼塊: { 若干程式碼 } 它們之間的區別主要如下: 靜態程式碼塊在虛擬機器載

Java中靜態成員變數靜態程式碼靜態內部類何時被初始化?

關於這個問題,本文不扯理論,直接上程式碼,通過結果來驗證結論,廢話少說,測試程式碼如下: public class StaticTest { public static StaticMember staticMember = new Static

java中非靜態內部類不能有靜態程式碼靜態方法、靜態變數

非靜態內部類相當於外部類中的非靜態成員變數,而如果外部類需要呼叫非靜態成員變數就需要先例項化才可以,如果非靜態內部類中有靜態方法塊,那麼又可以在載入類的時候提前載入,不需要考慮外部類的例項化,所以有矛盾,所以不可以。為什麼非靜態內部類中可以有靜態常量?(static fina

程式碼的解釋,構造程式碼靜態程式碼靜態常量和常量以及靜態成員變數和物件成員變數的區別

12  程式碼塊 就是一塊程式碼,是一對大括號括起來的內容  方法中:限制變數的生命週期 類中 方法外: 構造程式碼塊:沒有關鍵字修飾,在每次建立物件時,在構造方法執行前進行執行 用途:可以對成員 變

Java靜態程式碼靜態方法的區別/類載入順序

 (一)java 靜態程式碼塊 靜態方法區別  一般情況下,如果有些程式碼必須在專案啟動的時候就執行的時候,需要使用靜態程式碼塊,這種程式碼是主動執行的;需要在專案啟動的時候就初始化,在不建立物件的情況下,其他程式來呼叫的時候,需要使用靜態方法,這種程式碼是被動執行的.

static{}靜態程式碼{}普通程式碼之間的區別

轉載自:http://blog.csdn.net/aledavvv/article/details/16920743相同點:都是在JVM載入類時且在構造方法執行之前執行,在類中都可以定義多個,    一般在程式碼塊中對一些static變數進行賦值。不同點:靜態程式碼塊在非靜態

大括號{}的意義靜態程式碼建構函式的載入關係

import java.util.HashMap;import java.util.HashSet;import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import java.u

Java靜態程式碼靜態方法

1 靜態程式碼塊:有些程式碼必須在專案啟動的時候就執行,這種程式碼是主動執行的(當類被載入時,靜態程式碼塊被執行,且只被執行一次,靜態塊常用來執行類屬性的初始化) 2 靜態方法:需要在專案啟動的時候就初始化,在不建立物件的情況下,這種程式碼是被動執行的(靜態方法在類載入的時候就已經載入 可以用類

阿里java校招筆試題——程式碼中語句的執行順序

下面是阿里java校招的一道筆試題,程式碼如下: public class HelloA { //構造方法 public HelloA(){ System.out.println("Hello A!父類構造方法"); } //非靜態

java中靜態程式碼靜態方法、static關鍵字詳解

最近在準備面試,複習java基礎知識,對java中和static關鍵字相關的靜態方法、靜態程式碼塊、非靜態程式碼塊、靜態成員變數的用法進行了詳細的總結。 1. 靜態成員變數 宣告為static關鍵詞修飾的變數叫做靜態成員變數,也叫作全域性變數。被static修飾的成員變數和