Java类别载入器 |
1 Java的动态 特点 Java的动态 特点有两种,一是隐式的;另一种是显示的 。隐式的(implicit) 步骤便是当程式设计师用到new 这个Java 要害字时,会让类别载入器依需要载入您所需要的类别,这种 模式 使用了隐式的(implicit) 步骤 。显式的 步骤,又分成两种 模式,一种是藉由java.lang.Class 里的forName() 步骤,另一种则 是藉由java.lang.ClassLoader 里的loadClass() 步骤 。您 可以任意选用其中一种 步骤 。 2 隐式的动态 特点 在执行java文件时,惟独 径自的变量申明是不会载入相应的类的,惟独在用new生成实例时才载入 如示例所示: public class Main public static void main(String args[]) { A a1 = new A() ; B b1 ; } 类A和B 雷同,如下: public class A { public void print(“using A”); } 编译后,可用java –verbose:class Main运行, 视察输出 后果 。 可以看到JVM只载入了A,而没有载入B. 另外,类的载入只在执行到new一个类时,才载入,假如没有执行到new语句,则不载入 。 如://类Office public class Office { public static void main(String[] args) { Word myword=null; Excel myexcel=null; if (args[0].equals("Word")) { myword = new Word(); myword.start(); } if (args[0].equals("Excel")) { myexcel = new Excel(); myexcel.start(); } } } //类Word和Excel 根本 雷同,如下 public class Word { public void start() { System.out.println("using word"); } } 在dos命令 揭示符下,输入java –verbose Office Excel 可以看到JVM只载入Excel类,而不载入Word类 。 3 显示的动态 特点 3.1 java.lang.Class里的forName() 步骤 在上一个Office示例中,进行如下 批改: 一 加入Assembly类 public interface Assembly { public void start(); } 二 让Word和Excel类实现该接口 public class Word implements Assembly { public void start() { System.out.println("using word"); } } 三 Office 类如下所示 public class Office { public static void main(String[] args) throws Exception { java.lang.Class c = java.lang.Class.forName(args[0]); Object o = c.newInstance(); Assembly a = (Assembly)o; a.start(); } } 在命令 揭示符下输入java –verbose Office Word 输出入下: 通过上图你 可以看到,interface 如同class 普通,会由编译器产生一个独立的类别档(.class),当类别载入器载入类别时,假如发现该类别继承了 其余类别,或是实作了 其余介面,就会先载入代表该介面的类别档,也会载入其父类别的类别档,假如父类别也有其父类别,也会一并优先载入 。换句话说,类别载入器会依继承体系最上层的类别往下依序载入,直到全部的 先人类别都载入了,才轮到自己载入 。 下面介绍一下 forName 函数, 假如您亲自 搜索Java 2 SDK 注明档内部对於Class 这个类别的 注明,您 可以发现其实有两个forName() 步骤,一个是惟独一个参数的(便是之前程式之中所 使用的): public static Class forName(String className) 另外一个是需要三个参数的: public static Class forName(String name, boolean initialize,ClassLoader loader) 这两个 步骤,最後都是衔接到原生 步骤forName0(),其宣告如下: private static native Class forName0(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException; 惟独一个参数的forName() 步骤,最後叫用的是: forName0(className, true, ClassLoader.getCallerClassLoader()); 而 存在三个参数的forName() 步骤,最後叫用的是: forName0(name, initialize, loader); 这里initialize参数指,在载入类之后是不是进行初始化,关于该参数的作用可用如下示例 视察: 类里的静态初始化块在类第一次被初始化时才被呼叫,且仅呼叫一次 。在Word类里,加入静态初始化块 public class Word implements Assembly { static { System.out.println("word static initialization "); } public void start() { System.out.println("using word"); } } 将类Office作如下转变: public class Office { public static void main(String[] args) throws Exception { Office off= new Office(); System.out.println("类别 预备载入"); java.lang.Class c = java.lang.Class.forName(args[0],true,off.getClass().getClassLoader()); System.out.println("类别 预备实体化"); Object o = c.newInstance(); Object o2 = c.newInstance(); } }
|