JAVA中类文件加载是动态的。JVM指令是被封装在了. class文件里面,而.class文件的加载过程是动态的,也就是说当我们用到的时候才会去加载,如果不用的话,就不会去加载我们的类。这里所说的用到包括两种方式,第一种就是new一个对象的时候(这个时候要特别注意,当设计到多态的时候,就会有一点点变化,这时候编译器会做一些优化,这样以来当加载的时候会提前加载设计到多态的类,关于这一点下面有个例子(example 1)来说明。另一种就是当一个类的静态代码被调用的时候。
java 代码
//example 1
// Zoo.java
abstract class Animal {
Animal(){
System.out.println("Animal constructor");
}
}
class Tiger extends Animal {
Tiger(){
System.out.println("Tig constructor ");
}
}
class Dog extends Animal {
Dog(){
System.out.println("Dog Constructor ");
}
}
public class Zoo {
private Animal am; //Example 1.1
//private Dog am; Example 1.2
private Tiger tiger;
Zoo(){
tiger = new Tiger();
am = new Dog();
}
public static void main(String [] args){
System.out.println("new Zoo before");
Zoo z = new Zoo();
System.out.println("new Zoo after ");
}
}
当我们注释掉Example.1.1行时,运行Example1.2行,结果如下:
Example 1.2
分析以上两图的运行结果我们可以看出:当我们将子类对象赋值给父类时,编译器会做一点优化,于是加载器在还没有new 子类对象的时候已经加载了父类以及子类(example1.1结果),当不存在多态的时候,我们可以看到是当要new Dog()的时候才会加载Dog以及父类。无论何种方式,在new之前,类确实已经加载到了内存中。
JAVA为我们提供了两种动态机制。第一种是隐式机制。其实new一个对象和调用类的静态方法时,就是隐式机制在工作。第二种是显示机制。显示的机制又有两种策略(第一种是用java.lang.Class的forName(String str)方法,第二种是用java.lang.ClassLoader的loadClass())。
第一种:利用forName方法
当我们查API文档就会发现forName方法有两种形式。分别如下:
public static Class<?> forName(String className)
throws ClassNotFoundException
public static Class<?> forName(String name,
boolean initialize,
ClassLoader loader)
throws ClassNotFoundException