2017-07-07 77 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,请你投票并接受我的回答。 –