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")); 

运行是一个构造器(因为它在构造器内部!)。 运行构造函数的一部分是:运行 class.

的所有非静态初始化程序块

鉴于:

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

只 运行 你的 static 初始值设定项 - 但 没有 构造函数代码(它确实 - 但 那一行之后)。

所以你的问题是这个初始化块:

{
    dat1 = new ArrayList<>(); 
}

不是静态的

换句话说:您的问题是由 static/non-static 以非常不健康的方式混合引起的。如果字段是 static,请确保 static 初始化代码将初始化它。

顺便说一句:合理的解决方案是简单地做:

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

这样可以确保尽快初始化列表;然后编译器甚至会在您忘记初始化它时告诉您。

这段代码

{
    dat1 = new ArrayList<>(); 
}

这个构造函数块。这将在 super() 之后的每个构造函数中执行,因此它不会 运行 在 Mark1 上。

如果您有这样的代码,它将在 class 加载时执行。

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

这里有更多细节 http://www.jusfortechies.com/java/core-java/static-blocks.php

您的代码:

{
    dat1 = new ArrayList<>(); 
}

是一个非静态初始化器。当您使用 new StaticTest() 调用构造函数时,将调用它。之后dat1会被初始化。

您可以通过在代码前面添加 static 关键字来将您的代码更改为静态初始化:

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

那么这两种情况都适用。

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

实例块在您创建该 class 的实例时执行。 问你为什么得到 NullPointerException :- 请找到下面的 StaticTest class 执行流程:-

  1. 首先,所有导入 class 将像这样加载:-
    1. Object class 2.java.lang 包 Class 3.java.util.ArrayList Class.
  2. 编译器通过 StaticTest Class 并为您的情况下的所有静态成员分配内存 dat1.
  3. 现在 javac 编译器搜索用于执行的静态块。在你的情况下,它们不是静态块。
  4. 现在编译器执行 main 方法并执行 System.out.println(dat1.contains("a")); 被调用为 null.contains("a"); 这表明执行但正如我所说Instance 块在您创建该 class 的实例时执行。所以 dat1 在你创建对象 new StaticTest();
  5. 时被初始化