类加载带来的数据不一致的”坑“

首先观察下面代码,并想下输出结果是什么

public class SinglePattern{

    private static SinglePattern instance = new SinglePattern();//在类的装载就直接实例化
    public static int a;
    public static int b = 2;

    private SinglePattern(){
        a++;
        b++;
    }
    public static SinglePattern getInstance() {
        return instance;
    }

    public static void main(String[] args) {
        SinglePattern ins = SinglePattern.getInstance();
        System.out.println("a:="+ins.a);
        System.out.println("b:="+ins.b);
    }
}

上面就是一个单例模式呗

然后我不做任何修改,改变类实例化的一行代码的位置,想想输出结果是什么?

public class SinglePattern{

    public static int a;
    public static int b = 2;

    private static SinglePattern instance = new SinglePattern();//在类的装载就直接实例化

    private SinglePattern(){
        a++;
        b++;
    }
    public static SinglePattern getInstance() {
        return instance;
    }

    public static void main(String[] args) {
        SinglePattern ins = SinglePattern.getInstance();
        System.out.println("a:="+ins.a);
        System.out.println("b:="+ins.b);
    }
}

想到结果了没??

第一个运行结果为:
这里写图片描述

第二个运行结果为:
这里写图片描述

WTF?

就改变一行代码的位置,没有其它大的改动,就结果不一样了!!

其实这是类加载过程产生的问题,对类加载过程详细了解。可以参考:https://blog.csdn.net/weijifeng_/article/details/79894742

对于两个代码分析详解

1 .准备阶段

instance = null;
a = 0;
b = 0;

2 .初始化阶段

new SinglePattern() ; a = 1; b = 1;
public static int a;  a没有指定值,就是上一步的1
public static int b = 2; b有指定初始值,初始化阶段时,b = 2;

所以这就是第一种执行结果为a = 1, b = 2的原因了

1 .准备阶段

instance = null;
a = 0;
b = 0;

2 .初始化阶段

public static int a;  a没有指定值,就是上一步的0
public static int b = 2; b有指定初始值,初始化阶段时,b = 2;  
new SinglePattern() ; a = 1; b = 3;

这就是产生结果不一样的原因了!
类加载的准备阶段和初始化阶段都严格执行自己的工作,并且在初始化阶段,严格按照指令从上到下的顺序就行内存值分配

所以在了解装载的过程,就应该清楚自己取什么阶段的值,保证取值不会发生错误

猜你喜欢

转载自blog.csdn.net/weijifeng_/article/details/79968823