懒汉式单例中有一种实现方式是通过静态内部类,利用 Java 静态内部类的加载机制,那 Java 类的加载顺序究竟是如何的呢?
结论
- 代码执行顺序:静态代码块(仅一次) -> 非静态代码块(每次创建对象都一定会被执行) -> 构造方法
- 类加载顺序:如果存在内部类,外部类加载时不会加载内部类,内部类被加载时优先加载外部类
实验
public class ClassLoaderStudy {
static { System.out.println("外部静态代码块"); }
{ System.out.println("外部非静态代码块"); }
public ClassLoaderStudy() { System.out.println("外部无参构造方法"); }
public ClassLoaderStudy(String a) { System.out.println("外部有参构造方法"); }
public static String str = "外部静态字段";
static class StaticInner {
static { System.out.println("内部静态代码块"); }
public static String innerStr = "内部静态字段";
}
class Inner {
//非静态内部类不能创建静态代码块
{ System.out.println("内部非静态代码块"); }
public Inner() { System.out.println("内部非静态无参构造方法"); }
}
}
- 访问静态字段
访问静态字段时,先初始化类,静态代码块会被执行
如果 ClassLoaderStudy.str 字段被 final 修饰,则『外部静态代码块』不会输出,是因为 final 修饰之后就是常量,常量是被存在静态常量池中的,不需要加载类就可以访问
- 其他访问情况
可见执行顺序是:
静态代码块(仅一次) -> 非静态代码块(每次创建对象都一定会被执行) -> 构造方法
如果存在内部类,外部类加载时不会加载内部类,内部类被加载时优先加载外部类