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(); } }
|
|
来自: 昵称42536845 > 《java》