网学网为广大网友收集整理了,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();
}
}