簡體   English   中英

Java中的靜態初始化?

[英]Static Initialization in Java?

我正在嘗試執行以下代碼:

public class StaticTest {

    private static List<String> dat1;
    {
        dat1 = new ArrayList<>(); 
    }

    private StaticTest(){
        System.out.println(dat1.contains("a")); //Marked Line 2: this one is not throwing
    }

    public static void main(String[] args) {
        System.out.println(dat1.contains("a")); //Marked Line 1: This line throws null pointer 
        new StaticTest(); 
    }
}

我嘗試執行上述代碼,在標記行1處得到了Null pointer exception 。但是當我注釋標記行1時,得到了輸出。

為什么我在第一種情況下而不在第二種情況下得到例外?

當我使用private static List<String> dat1= new ArrayList<>(); ,不會引發異常。

簡單:

System.out.println(dat1.contains("a")); 

運行一個構造函數(因為它在構造函數內部!)。 運行構造函數的一部分是:運行類的所有非靜態初始化程序塊。

鑒於:

public static void main(String[] args) {
  System.out.println(dat1.contains("a")); //Marked Line 1: This line 

只運行您的靜態初始化程序-但運行構造函數代碼(確實- 該行之后)。

因此,您的問題是此初始化程序塊:

{
    dat1 = new ArrayList<>(); 
}

不是靜態的

換句話說:您的問題是由以非常不健康的方式混合靜態/非靜態引起的。 如果字段是static ,請確保使用靜態初始化代碼將其初始化。

順便說一句:合理的解決方案是簡單地做:

private final static List<String> data = new ArrayList<>();

這樣可以確保盡快初始化列表。 然后編譯器甚至會在您忘記初始化時告訴您。

這段代碼

{
    dat1 = new ArrayList<>(); 
}

此構造函數塊。 將在super()之后的每個構造函數中執行該函數,因此它將不會在Mark1上運行。

如果您有這樣的代碼,則將在加載類時執行它。

static {
    dat1 = new ArrayList<>(); 
}

更多詳細信息, 請參見http://www.jusfortechies.com/java/core-java/static-blocks.php

嗨@kajal,請參考以下正確的代碼:-

 public class StaticTest {

    private static List<String> dat1;
    static
    {
        dat1 = new ArrayList<String>(); 
    }

    private StaticTest(){
        System.out.println(dat1.contains("a")); //Marked Line 2: this one is not throwing
    }
    public static void main(String[] args) {
        System.out.println(dat1.contains("a")); //Marked Line 1: This line throws null pointer 
        new StaticTest(); 
    }
}

創建該類的實例時,將執行實例塊。 質疑為什么要獲取NullPointerException :-請找到下面的StaticTest類執行流程:-

  1. 首先,所有導入類的加載方式如下:
    1. Object類2. java.lang包類3. java.util.ArrayList類。
  2. 編譯器將遍歷StaticTest類,並為所有靜態成員(如果是dat1分配內存。
  3. 現在,javac編譯器將搜索Static塊以進行執行。 在您的情況下,它們不是靜態塊。
  4. 現在,編譯器執行main方法並執行System.out.println(dat1.contains("a")); 被稱為null.contains("a"); 解決了執行問題,但是正如我所說的,當您創建該類的實例時,將執行Instance塊。 因此,在創建對象new StaticTest();時會初始化dat1 new StaticTest();

您的代碼:

{
    dat1 = new ArrayList<>(); 
}

是一個非靜態初始化器。 當您使用以下方法調用構造函數時,將調用此方法: new StaticTest() 之后, dat1將被初始化。

您可以在代碼前面加上static關鍵字,從而將其更改為靜態初始化:

static
{
    dat1 = new ArrayList<>(); 
}

然后它將適用於兩種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM