简单概括:当主动使用此类时,就会被加载,分为以下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进阶全套博客

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐