需要前置技能
- 接口
- 抽象类
- 实现
- 继承
类的生命周期
- 加载
- 连接 (连接又分为 验证、准备、解析)
- 初始化
- 使用
- 卸载
说说准备和初始化阶段
准备:
为静态变量分配内存和初始化默认值
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
延伸出一个知识点:
默认值:
- 基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。
- 引用类型的默认值为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