java Class被加载的时机

简单概括:当主动使用此类时,就会被加载,分为以下6种情况:
1.创建类的实例
2.访问某个类或者接口的静态变量,或者对该静态变量赋值
3.调用类的静态方法
4.反射(Class.forName())
5.初始化类的子类
6.java虚拟机启动时的main方法所在类

下面用代码来举例:
首先要明白的是,类被加载判断:类中的静态代码块会执行。

实例一:

public class ClassLoaderTest {
	public static void main(String[] args){
		//加了final后编译期确定,所以不会加载Target类
		System.out.println(Target.x);
	}
}
class Target {
	public static final int x = 6 / 3 ;
	static {
		System.out.println("Target类被加载了");
	}
}
// 结果 : 2

实例二:

public class ClassLoaderTest {
	public static void main(String[] args){
		//会加载Target类
		System.out.println(Target.x);
	}
}
class Target {
	public static int x = 6 / 3 ;
	static {
		System.out.println("Target类被加载了");
	}
}
// 结果 : Target类被加载了   2

实例三:

public class ClassLoaderTest {
	public static void main(String[] args){
		//都是使用父类的 ,不会加载子类Target类
		System.out.println(Target.x);
		Target.p();
	}
}
class Parent{
	static int x = 0;
	static void p(){
	}
}
class Target {
	static {
		System.out.println("Target类被加载了");
	}
}
//结果  0

实例四:

public class ClassLoaderTest {
	public static void main(String[] args){
		// 获得应用类加载器
		ClassLoader appLoader = ClassLoaderTest.class.getClassLoader().getSystemClassLoader();
		Class tClazz = appLoader.loadClass("Target");//这里不会导致Target类被加载,只是加载文件成二进制
		System.out.println("loadClass");
		tClazz.newInstance(); // 这里就会导致Target被加载
	}
}
class Target {
	static {
		System.out.println("Target类被加载了");
	}
}
// 结果 : loadClass   Target类被加载了

最后来一个奇怪的实例

public class ClassLoaderTest {
	public static void main(String[] args){
		Target.getInstance();
		System.out.println(Target.a + ","+Target.b);
	}
}
class Target {
	private static final Target t = new Target();
	static int a ;
	static int b = 0;
	private Target(){
		a++;
		b++;
	}
	public static Target getInstance(){
		return t ;
	}
}
//这里大家猜下结果会是神马?
A 1,0
B 0,1
C 0,0
D 1,1

很多人可能会猜到肯定是打印 1,1 啊 ,都不用想啊,实际并非如此!应该是1,0
分析: 首先编译期间,各静态变量都声明了,等号右边的这时都还不用管。然后加载Target类时 ,静态从上往下看,static final Target会导致构造执行,a和b 都加1 ,此时a和b都是1 ,然后 到b时,主动又赋值为0 ,所以b会从1变到0,而a不变。

如果将Target变成这样

class Target {
	static int a ;
	static int b = 0;
	private static final Target t = new Target();
	private Target(){
		a++;
		b++;
	}
	public static Target getInstance(){
		return t ;
	}
}
// 结果   1 , 1

谢谢大家,完毕!来句闲话,深圳有爱好音乐的会打鼓的程序员可以一起交流加入我们乐队一起嗨。我的QQ:657455400

强烈推荐一套Java进阶博客,都是干货,走向架构师不是梦!

Java进阶全套博客

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值