破坏单例模式之静态方法、静态代码块和构造方法执行顺序

时间:2021-07-14 16:26:05

昨天看了凯子哥的单例设计模式,里面讲到了破坏单例模式的方法,具体内容请看原文,这里来分析一下原理。为什么通过静态代码块就会破坏单例模式呢,这就是今天要讲的故事:静态代码块在什么时候执行?
上代码

class Parent {
    {
        System.out.println("i am parent block");
    }
    static {
        System.out.println("i am parent static block");
    }
    public Parent() {
        System.out.println("i am parent constructor");
    }
}
class Child extends Parent {
    {
        System.out.println("i am child block");
    }
    static {
        System.out.println("i am child static block");
    }
    public Child() {
        System.out.println("i am child constructor");
    }
}

这个时候new Child(),会发生什么?

i am parent static block
i am child static block
i am parent block
i am parent constructor i am child block i am child constructor

从上面的打印结果来看,static block的优先级最高,先执行父类的static block->执行子类的static block->父类普通block->父类的constructor->子类普通block->子类constructor


这就是为什么当在静态代码块里面去new对象的时候,会破坏单例模式,因为静态代码块是主动执行的,当加载到的这个class文件内有静态代码块,那么静态代码块会先去执行,静态代码块里面初始化了一次,手动调用的时候又初始化了一次。
如果是静态内部类实现的单例模式,这种破坏方法不起作用,静态内部类只会执行一次,当SingletonDestyoyer中的静态代码块去调用SingletonStatic.getInstance()的时候,静态内部类还没有初始化完成,返回null,不会出现多次初始化的情况。
Ps:这块还是有点迷糊,如果有明白人,欢迎交流!!!