1.类的加载,链接,初始化
注意点:
- Class对象是在类的加载过程中生成的(类的数据(static,常量,代码)在方法区,Class类对象在堆中),这个Class类对象作为方法区中类数据的访问入口
- 类的链接过程中:为static变量分配了内存(方法区)和设置了默认初始值
- 类的初始化:先执行类构造器(对类变量赋值,执行静态代码块),再调用构造方法。
2.类的初始化
何时会发送类的初始化?
当对类进行主动引用时,会发生类的初始化
对应的,当对类进行被动引用时,不会发生类的初始化
类的被动引用测试代码:
package AnnotationTest;
public class A5 {
static{
System.out.println("Initialize class A5 (main) ");
}
public static void main(String[] args) {
System.out.println(Rabbit.id);
Rabbit[] r = new Rabbit[10];
System.out.println(Rabbit.f);
}
}
class Animal{
static {
System.out.println("Initialize class Animal");
}
static int id = 10;
}
class Rabbit extends Animal{
static {
System.out.println("Initialize class Rabbit");
}
static int num = 99;
static final int f = 2;
}
3.类的加载器
双亲委派机制:
当一个类加载器收到一个类加载请求时,会将请求先委托给父类加载器去完成,若父类加载器无法完成,才会由这个加载器来加载该类。
所以如果出现自定义的类与Java库中类重名时(比如java.util.ArrayList),会加载Java库中 的类,而非自定义的类。
四类加载器:
- Bootstrap ClassLoader:无法直接获取,通过子类getParent(),只能得到null
- Extention ClassLoader
- Application ClassLoader:会加载classpath下的所有类,包括了用户自定义的类
- User ClassLoader:加载指定路径的类
测试代码:
package AnnotationTest;
public class A6 {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
ClassLoader root = parent.getParent();
System.out.println(root);
ClassLoader loader = Class.forName("AnnotationTest.A6").getClassLoader();
System.out.println(loader);
loader = Class.forName("java.util.ArrayList").getClassLoader();
System.out.println(loader);
System.out.println(System.getProperty("java.class.path"));
}
}