public class Singleton { public static Singleton s=new Singleton(); public static int k1; public static int k2=0; private Singleton(){ k1++; k2++; } public static void main(String[] args) { System.out.println(Singleton.k1); System.out.println(Singleton.k2); } }
如果是下面这样呢?
public class Singleton { public static int k1; public static int k2=0; public static Singleton s=new Singleton(); private Singleton(){ k1++; k2++; } public static void main(String[] args) { System.out.println(Singleton.k1); System.out.println(Singleton.k2); } }
加载: 查找并加载类的二进制数据
连接:
-验证 确保被加载的类的正确性
-准备 为类的静态变量分配内存,并将其初始化为默认值(int就是0 boolean就是 false 引用类型就是null)
-解析 把类中的符号引用变为直接引用
初始化: 为类的静态变量赋予正确的初始值
不知道诸位看官是否有什么疑问?
如果大家没有,我倒是有个问题,在我们最开始编写java的时候总是javac命令编译成class字节码,java命令运行。如果java代码有什么问题,在javac的时候就会抛出问题,换句话说等我们连接class文件的时候它肯定是没问题的,那还验证什么呀?
答案就是:
如果class的产生只能通过javac命令的话,那就没有任何问题了,可关键就是人们也可以手动产生class文件,所以验证这一步还是有用的。
第二个问题 在连接的准备阶段有把静态变量初始为默认值,但是在初始化的阶段也有为类的静态变量赋予正确的初始值。这两个步骤有什么关系?
看如下代码片
public class test{ public static int a=5; public static int b; public static int c; static{ c=10; } public static Person p; }
类的加载的最终产品是位于堆区中的Class对象
这里就有另一个名词了Class对象。
就像每一本书有作者,价格等描述自身一些熟悉的信息,每个类也都有一个描述自己信息的东西,它就是class对象。
例如
public class Person{
public String name;
public String getName(){
return name;
}
}
这个类的Class对象里就包含了这个类里面有几个属性,每个属性是什么类型,有什么方法,每个方法的参数都是什么,返回值都是什么等等。
具体信息,参考api。
谈到类的加载,就得说说类的加载器了。
java中有两种类的加载器
– Java虚拟机自带的加载器
根类加载器(Bootstrap)
(用c++实现 大家都看不到)
扩展类加载器(Extension)
系统类加载器(System)
(扩展类加载器与系统类加载器是用java写的)
-用户自定义的类加载器
java.lang.ClassLoader的子类
用户可以定制类的加载方式
看如下代码片
Class c1=Class.forName("java.lang.String"); Class c2=Class.forName("Singleton"); //就是上面的那个Singleton System.out.println(c1.getClassLoader()); System.out.println(c2.getClassLoader());运行结果就是
至于什么是符号引用,大家在eclipse中,打开一个class文件
上面红框里面的就是符号引用
除了以上六种,别的调用方法都是被动使用。
再说说最开始的那个题目
public static Singleton s=new Singleton(); public static int k1; public static int k2=0; private Singleton(){ k1++; k2++; }在连接的准备阶段 k1,k2都是0,s是null
到了初始化阶段, s的初始化调用了构造函数
k1,k2都从0编程了1
继续往下阅读
public static int k1; public static int k2=0;k1没有被赋值还是1
但是k2却被赋值为0了
所以最后的结果就是
1
0
至于把
public static Singleton s=new Singleton();
放到后面,大家自己分析吧.
原文地址:http://blog.csdn.net/dlf123321/article/details/39957175