类加载的时机(初始化的时机)

package com.nefu.testJVM;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.Test;

public class TestClassLoader extends Father{
	
	static {
		System.out.println("我是ClassLoader,我被加载了!!!");
	}
	
	/**
	 * 类加载中的主动引用的五种场景(有且只有这五种情况会触发类加载)
	 * 1.使用new实例化对象(数组对象不会)或者调用一个类的静态字段(static final类型的字段不会触发类加载)
	 * 2.使用java.lang.reflect中的方法对类进行反射调用
	 * 3.初始化一个子类,发现其父类未初始化,加载其父类。
	 * 4.main方法所在的类(public修饰的类)会在虚拟机启动时被加载。
	 * 5.但是用动态语言支持时,如果一个java.lang.invoke.MethodHandle实例后解析结果REF_putStatic,REF_getStatic,
	 * REF_invokeStatic的方法句柄时,当改方法句柄对应的类没有初始化时,需要初始化该类。(动态语言支持详情请查看)
	 * 
	 * 类加载的先后(main方法所在类>父类>子类)
	 */
	
	//情景一:使用new实例化一个对象
	@Test
	public void test01() {
		new TestClassLoader();
	}
	
	//情景二:调用一个类的静态字段
	@Test
	public void test02() {
		System.out.println(A.a);
	}
	
	//情景三:使用java.lang.reflect包中的方法对类进行反射调用
	@Test
	public void test03() throws ClassNotFoundException {
//		Class clazz = Class.forName("com.nefu.testJVM.A");
		Class clazz = A.class;
		Method [] methods = clazz.getDeclaredMethods();
		for(Method m:methods) {
			System.out.println(m);
		}
//		System.out.println(clazz.getName());
		Field [] fields = clazz.getDeclaredFields();
		for(Field f:fields) {
			System.out.println(f.getName());
		}
	}
	
	//情景四:父类未加载时,加载父类(加载优先级TestClassLoader>Father>Son)
	@Test
	public void test04() {
		Son son = new Son();
	}
	
	
	//情景五:TestClassLoader继承自Father类,优先加载Father类
	@Test
	public void test05() {
		Son son = new Son();
	}
	
	//----------------------------------------------------------
	
	
	//情景六:通过子类引用父类对象(不会触发主动引用)
	@Test
	public void test06() {
		System.out.println(Son.a);
	}
	
	//情景七:通过数组定义引用类(不会触发主动引用)
	@Test
	public void test07() {
		A [] as = new A[10];
	}
	
	//情景八:引用常量(不会触发主动引用,常量再编译器存入常量池,本质上使用的是直接从常量池中取出的常量)
	@Test
	public void test08() {
		System.out.println(A.c);
	}
}


class A{
	static int a = 10;
	int b ;
	static final int c = 10; //这种情况下不会触发类加载
	static {
		System.out.println("我是A,我被加载了!!!");
	}
	
	void f() {
		
	}
}

class Father{
	static int a = 10;
	static {
		System.out.println("我是father,我被加载了");
	}
}

class Son extends Father{
	static {
		System.out.println("我是son,我被加载了");
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43695091/article/details/89349389