昨天看到这样一篇帖子,讨论类加载顺序的,也可以说是初始化顺序的,今天早上找不到了,本来想回复的,现在自己写博客回复了,呵呵
public class Singleton {
private static Singleton obj = new Singleton();
public static int counter1 ;
public static int counter2 = 0;
private Singleton()
{
counter1++;
counter2++;
}
public static Singleton getInstance()
{
return obj;
}
public static void main(String[] args) {
Singleton.getInstance();
System.out.println("obj.counter1=="+counter1);
System.out.println("obj.counter2=="+counter2);
}
}
我不了解为什么obj.counter1=1,obj.counter2=0.希望给我说说
刚开始也很迷茫,我想不通的问题是什么时候声明的变量count1、count2?
以前的理解它的执行顺序应该是这样的:
1、加载类,当然首先执行的是
private static Singleton obj = new Singleton();
2、所以出现了对中对象的创建,于是执行构造方法:
private Singleton()
{
counter1++;
counter2++;
}
3、按照顺序,应该执行下一条语句,即:
public static int counter1 ;
public static int counter2 = 0;
好了,类的加载过程完成了。
现在才开始执行main方法的第一条语句,随后的结论都成立了。
现在的问题出现了:什么时候声明的变量count1、count2?
查询了一些资料,终于解决了,我认为应该是这样的:
类加载的顺序其实以上的说法是有误的,也就是以前的理解是存在偏差的,除非出现想文章这样的程序才会暴露出来。好了,废话少说,看看真正的类加载顺序:
类加载分为三个过程:装载、链接、初始化。
装载的过程就是将class文件读入内存的过程,并且提取其中的类关键信息,比如:方法、变量等等。
而在链接中存在三个步骤:
a、进行字节码的检查,看是否符合class文件规范;
b、对类中的类变量进行分配空间,附初始值。此处专指基本类型。
c、对类中的引用变量进行分配空间。
随后才进行初始化,现在的初始化才是真正的,将按照语句一句一句执行了。
也就是说,在初始化执行以前所有的类变量以及引用变量都是分配了存储空间的,只是他们的数值是不可信任的,也就是系统默认的数据。
现在问题终于搞明白了。
所以有这样一个建议,或者说以前有人提醒的问题:
在进行构造方法中不允许进行业务逻辑的处理,只是进行简单的数据初始化,不然会出现意想不到的结果。
这个程序说明了这个问题。
如果将
private static Singleton obj = new Singleton();
public static int counter1 ;
public static int counter2 = 0;
变换为
public static int counter1 ;
public static int counter2 = 0;
private static Singleton obj = new Singleton();
则执行结果则由
obj.counter1=1,obj.counter2=0
变成了
obj.counter1=1,obj.counter2=1.
这下明白了吧。
Java中奇怪而又无可厚非的类加载顺序
最新推荐文章于 2024-10-11 17:30:36 发布