您当前的位置:首页 > 计算机 > 编程开发 > Java

一个静态变量的空指针异常

时间:02-10来源:作者:点击数:

代码如下:

public class Main {

    public static void main(String[] args) throws Exception {
        Foo foo = Foo.getInstance();
    }

}

class Foo {

    private static Foo instance = new Foo();
    private static List<String> list = new ArrayList<>();

    public static Foo getInstance() {
        return instance;
    }

    public Foo() {
        list.add("Hello");
    }
}

运行时异常如下:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.company.Main.main(Main.java:11)
Caused by: java.lang.NullPointerException
	at com.company.Foo.<init>(Main.java:26)
	at com.company.Foo.<clinit>(Main.java:18)
	... 1 more

通过异常可知是这行代码出了空指针异常:list.add("Hello");,很明显,list对象为空,我这个代码已经是简化之后的,在真实项目中代码很多的时候是有点懵人,list是一个静态变量,而Foo()函数是一个实例函数,一般理解就是静态变量先初始化的啊,为什么会是空啊!没错,静态变量先初始化,但是这里Foo实例也是在静态变量中直接初始化的:private static Foo instance = new Foo();,所以这行代码先执行了,先要初始化instance这个静态变量,而你在初始化这个变量的时候又用到了另一个静态变量list,而这个静态变量声明是在后面的,所以还没初始化到,所以就为null了,解决方案有两种:

方式一:把list声明在instance的前面,如下:

class Foo {
    public static List<String> list = new ArrayList<>();
    private static Foo instance = new Foo();
}

这样我们在调用Foo.getInstance()的时候,它就加载了Foo的Class到内存中,一加载Class就会初始化静态变量,多个静态变量是按声明的先后顺序声明的,所以list先声明就会先初始化,然后在初始化instance,此时的list就不为空了。

方式二:不修改list的声明位置也没关系,但是需要把liststatic修饰符去除掉,如下:

class Foo {
    private static Foo instance = new Foo();
    public List<String> list = new ArrayList<>();
}

Foo的字节码一加载进内存就会初始化静态变量instance,而instancenew了一个Foo()对象,所以此时会初始化Foo上面的成员变量list(非静态成员变量),所有的成员变量都初始化完成之后,再会执行Foo()构造函数中的代码,所以此时list也不会为空了。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门