• ExceptionInInitializerError


    代码如下:

    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");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行时异常如下:

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过异常可知是这行代码出了空指针异常: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();
    }
    
    • 1
    • 2
    • 3
    • 4

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

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

    class Foo {
        private static Foo instance = new Foo();
        public List<String> list = new ArrayList<>();
    }
    
    • 1
    • 2
    • 3
    • 4

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

  • 相关阅读:
    电商秒杀项目收获(二)
    商业合作保密协议书(公对公)【设计】
    分布式事务之基于可靠消息的最终一致性架构设计方案
    【企业数字化】企业数字化技术应用5大技术趋势
    Java开发:反射机制
    【阅读笔记】后真相时代的竞争性真相
    【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-Chapter21-sed 进阶
    聚观早报 | 中国新能源车企组团“出海”;盒马鲜生门店突破350家
    曲线艺术编程 coding curves 第九章 旋轮曲线(ROULETTE CURVES)
    ArcGIS绘制北半球俯视投影地图
  • 原文地址:https://blog.csdn.net/android_cai_niao/article/details/126224765