我试图执行以下代码:
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();
}
}
我尝试执行上面的代码,我在Marked Line 1上得到Null pointer exception
。但是当我评论Marked Line 1时,我得到了输出。
为什么我在第一种情况下获得异常而不在第二种情况下获得异常?
当我使用private static List<String> dat1= new ArrayList<>();
时,不会抛出任何异常。
答案 0 :(得分: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<>();
}
不是静态!
换句话说:你的问题是由非常不健康的方式混合静态/非静态引起的。如果字段静态,请确保静态初始化代码将初始化它。
顺便说一句:合理的解决办法就是:private final static List<String> data = new ArrayList<>();
这确保列表尽快初始化;然后编译器会告诉你什么时候忘记初始化它。
答案 1 :(得分:1)
此代码
{
dat1 = new ArrayList<>();
}
此构造函数块。这将在super()之后的每个构造函数中执行,因此它不会在Mark1上运行。
如果你有这样的代码,它将在加载类时执行。
static {
dat1 = new ArrayList<>();
}
这里有更多细节 http://www.jusfortechies.com/java/core-java/static-blocks.php
答案 2 :(得分: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
类执行的以下流程: -
Object
第2课。java.lang
包类3。java.util.ArrayList
类。dat1
。main
方法并执行System.out.println(dat1.contains("a"));
被称为 null.contains("a");
,它会执行该操作,但正如我所说的实例块执行当您创建该类的实例时。因此,当您创建对象dat1
new StaticTest();
醇>
答案 3 :(得分:0)
您的代码:
{
dat1 = new ArrayList<>();
}
是非静态初始化程序。当您使用:new StaticTest()
调用构造函数时,将调用此方法。之后dat1
将被初始化。
您可以将代码更改为静态初始化,方法是将其添加到static
关键字:
static
{
dat1 = new ArrayList<>();
}
然后它适用于两种情况。