2017-07-07 108 views
1

我試圖執行以下代碼:靜動初始化

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<>();時,不會引發異常。

回答

4

簡單:

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

靜態

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

BTW:合理的解決方案是簡單地做:

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

這可以確保這個列表是儘可能快初始化;然後編譯器甚至會在你忘記初始化時告訴你。

+0

非常感謝。我在塊之前錯過了「靜態」關鍵字。我測試過了,它按預期工作。 – Kajal

+0

是的,我接受了一個給定的答案.. :) – Kajal

1

此代碼

{ 
    dat1 = new ArrayList<>(); 
} 

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

如果你有這樣的代碼,它會在加載類時執行。

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

這裏更詳細 http://www.jusfortechies.com/java/core-java/static-blocks.php

+0

這是一個*初始值*塊。 –

0

您的代碼:

{ 
    dat1 = new ArrayList<>(); 
} 

是一個非靜態初始化。這稱爲,當你調用構造函數:new StaticTest()。之後dat1將被初始化。

您可以通過與static關鍵字之前它改變你的代碼的靜態初始化:

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

然後,它會爲這兩種情況下工作。

1

嗨@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");這trhows的execption但正如我所說的實例塊是當你創建一個類的實例執行。所以dat1在創建對象時被初始化new StaticTest();
+0

謝謝Husnain。我測試了代碼,它工作正常。 – Kajal

+0

嗨@kajal,請你投票並接受我的回答。 –