什么时候会发生类初始化(类的主动引用和类的被动引用)

什么时候会发生类初始化

前言

什么时候会发生类初始化

类的主动引用

如果在main()方法中去new一个子类的对象(子类继承了父类),那么JVM会自动初始化父类
 
由于这里是new子类(Son类),父类没有被初始化,所以JVM会自动初始化父类先

练习代码1(主动引用(new 的形式))
// 测试类什么时候会初始化
public class Test05 {
	
	static {
		System.out.println("Main类被加载");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 1、主动引用
		// 由于这里是new子类(Son类),父类没有被初始化,所以JVM会自动初始化父类先
		Son son = new Son();
	}
}

class Father{
	
	static int b = 2;
	
	// 静态代码块
	static {
		System.out.println("父类被加载");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子类被加载");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

运行结果:

Main类被加载
父类被加载
子类被加载
练习代码2(主动引用(反射的形式))
// 测试类什么时候会初始化
public class Test05 {
	
	static {
		System.out.println("Main类被加载");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 1、主动引用
		// 由于这里是new子类(Son类),父类没有被初始化,所以JVM会自动初始化父类先
//		Son son = new Son();
		
		// 反射也会产生主动引用
		Class.forName("com.lwm.reflection.Son");
	}
}

class Father{
	
	static int b = 2;
	
	// 静态代码块
	static {
		System.out.println("父类被加载");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子类被加载");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

结果与上面的一致
 
通过反射也是会产生类的主动引用,它会把所有东西加载进来(Main类被加载、父类被加载、子类被加载),这样会极大的消耗资源
 

类的被动引用

通过子类去调用父类的静态方法或者静态变量,不会对子类产生任何影响,子类不会被加载

练习代码1(被动引用(通过子类去调用父类的静态方法或者静态变量))
// 测试类什么时候会初始化
public class Test05 {
	
	static {
		System.out.println("Main类被加载");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 不会产生类的引用的方法
		
		// 通过子类去调用父类的静态方法或者静态变量,不会对子类产生任何影响,子类不会被加载
		System.out.println(Son.b);
	}
}

class Father{
	
	static int b = 2;
	
	// 静态代码块
	static {
		System.out.println("父类被加载");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子类被加载");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

运行结果:

Main类被加载
父类被加载
2
练习代码2(被动引用(通过数组形式))

数组占了一个空间,开辟了5个空间(如果没被加载说明什么都没干(此时只有main类被加载))

// 测试类什么时候会初始化
public class Test05 {
	
	static {
		System.out.println("Main类被加载");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 不会产生类的引用的方法
        
        // 通过一个数组
		// 数组占了一个空间,开辟了5个空间(如果没被加载说明什么都没干(此时只有main类被加载))
		Son[] array = new Son[5];
	}
}

class Father{
	
	static int b = 2;
	
	// 静态代码块
	static {
		System.out.println("父类被加载");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子类被加载");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

运行结果:

Main类被加载
为什么会加载Main类呢?

因为当虚拟机启动,就会先初始化main方法所在的类,然后才执行 Son[] array = new Son[5];这行代码,这时没有任何类被加载,这行代码只是一个数组,它只是一个名字和一片空间而已

练习代码3(被动引用(通过调用常量形式))
// 测试类什么时候会初始化
public class Test05 {
	
	static {
		System.out.println("Main类被加载");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 不会产生类的引用的方法
	
		// 调用子类的常量(常量并不会引起父类和子类的初始化)
		System.out.println(Son.M);
	}
}

class Father{
	
	static int b = 2;
	
	// 静态代码块
	static {
		System.out.println("父类被加载");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子类被加载");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

运行结果:

Main类被加载
1

所有的常量和类的静态变量都是在链接阶段就被赋了一个值,在链接阶段就做了,初始化的时候就已经存在了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值