浅谈类的准备和初始化

需要前置技能

  • 接口
  • 抽象类
  • 实现
  • 继承

类的生命周期

  1. 加载
  2. 连接 (连接又分为 验证、准备、解析)
  3. 初始化
  4. 使用
  5. 卸载

说说准备和初始化阶段

准备:
为静态变量分配内存和初始化默认值

package com.lazymax.base.jvm.classload;
public class Prepare {
    static int a;
}
class Test{
    public static void main(String[] args) {
        System.out.println("result: " + Prepare.a);
    }
}
// 结果:  
result: 0

延伸出一个知识点:
默认值:

  1. 基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。
  2. 引用类型的默认值为null。
package com.lazymax.base.jvm.classload;
public class Prepare {
    static final int a;
    static final Prepare prepare;
}
class Test{
    public static void main(String[] args) {
        System.out.println("result: " + Prepare.a);
        System.out.println("result: " + Prepare.prepare);
    }
}
// 结果:  
result: 0
result: null

初始化
主动引用(首次加载会导致初始化):

  • 通过new关键字实例化对象、读取或设置类的静态变量、调用类的静态方法。
  • 通过反射方式执行以上三种行为。
  • 初始化子类的时候,会触发父类的初始化。
  • 作为程序入口直接运行时(也就是直接调用main方法)
    其他情况叫做被动引用

特殊情况这种情况不会初始化类

package com.lazymax.base.jvm.classload;
public class Prepare {
    public static final String pools = "123";
}
class Test{
    public static void main(String[] args) {
        System.out.println(Prepare.pools);
    }
}
// 结果:  
123

为什么使用final?
final直接将数据放入使用类的常量池中,可以避免类的初始化、假如编译后把Prepare.class 删除打印结果依旧不变

父类也会初始化的情况

package com.lazymax.base.jvm.classload;
public class Prepare extends Parent{
    static String pools = "123";
}
class Parent{
    static {
        System.out.println("load");
    }
}
class Test{
    public static void main(String[] args) {
        System.out.println(Prepare.pools);
    }
}

父类不会初始化的情况

package com.lazymax.base.jvm.classload;
public class Prepare extends Parent{
    static final String pools = "123";
}
class Parent{
    static {
        System.out.println("load");
    }
}
class Test{
    public static void main(String[] args) {
        System.out.println(Prepare.pools);
    }
}

静态参数初始化
顺序为自上而下

package com.lazymax.base.jvm.classload;
public class Prepare{
    static {
        pools = "66";
    }
    static String pools = "123";
}
class Test{
    public static void main(String[] args) {
        System.out.println(Prepare.pools);
    }
}
// result:  
123

接口示例

package com.lazymax.base.jvm.classload;
public interface Prepare extends Parent{
    String pools = "123";
}
interface Parent{
    Demo demo = new Demo();
}
class Demo{
    static {
        System.out.println("load");
    }
}
class Test{
    public static void main(String[] args) {
        System.out.println(Prepare.pools);
    }
}
// result
123

总结
对final的常量直接引用不会导致类的初始化
非final静态变量

package com.lazymax.base.jvm.classload;
public class Prepare {
    static final Demo pools = new Demo();
    static {
        System.out.println("load");
    }
}
class Demo{
    static {
        System.out.println("demo load");
    }
}
class Test{
    public static void main(String[] args) {
        System.out.println(Prepare.pools);
    }
}
// result  
demo load
load
com.lazymax.base.jvm.classload.Demo@3cb5cdba

感谢
深入理解JVM-张龙(bilibili)

你可能感兴趣的:(浅谈类的准备和初始化)