我们先看一段看起来很纠结的代码
package org.classloader;
public class Singleton {
private static Singleton singleton=new Singleton();
public static int count1;
public static int count2=0;
public Singleton()
{
count1++;
count2++;
}
public static Singleton getInstance()
{
return singleton;
}
public static void main(String args[])
{
Singleton singleton=Singleton.getInstance();
System.out.println(singleton.count1);
System.out.println(singleton.count2);
}
}
结果是 1 0 你分析正确了么,如果没有回顾一下,深入虚拟机(1)和(2)的内容
静态代码的执行是自上而下的先后顺序
1.类的初始化步骤
2.初始化时机
• 主动使用(六种)
– 创建类的实例
– 访问某个类或接口的静态变量,或者对该静态变量赋值
– 调用类的静态方法
– 反射(如Class.forName(“com.shengsiyuan.Test”))
– 初始化一个类的子类
– Java虚拟机启动时被标明为启动类的类(Java Test)
除了上述情况都不会导致类的初始化
只有当程序访问的静态变量或静态方法确实在当前类或当前接口中定义时,才可以认为是对类或接口的主动使用【如果有继承关系,访问父类的静态方法不会是类的主动使用】
【编译时能确定的变量 static final 不会导致类的初始化】
public class Singeleton extends Singleton {
public static void main(String args[])
{
System.out.println(aa.getInstance());
}
}
class aa extends Singleton
{
static
{
System.out.println("22");
}
}
输出没有22 因为访问不是本类的静态变量
调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化。