java类的动态加载
时间:2010-06-10 来源:lzn_sc
(1)
JAVA中类文件加载是动态的。也就是说当我们用到的时候才会去加载,如果不用的话,就不会去加载我们的类。
JAVA为我们提供了两种动态机制。第一种是隐式机制。第二种是显示机制。如下:
两种方法:
|
+-- 隐式机制 :new一个对象 + 调用类的静态方法
|
+-- 显式机制 :
|
+-- 由 java.lang.Class的forName()方法加载
|
+-- 由 java.lang.ClassLoader的loadClass()方法加载 (2)使用Class.forName()
Class.forName()方法具有两个形式:
+- public static Class forName(String className)
|
+- public static Class forName(String className, boolean initialize,ClassLoader loader)
参数说明:
className - 所需类的完全限定名 (必须包含包名,否则出错!)
initialize - 是否必须初始化类 (静态代码块的初始化)
loader - 用于加载类的类加载器
调用只有一个参数的forName()方法等效于 Class.forName(className, true, loader)。
这两个方法,最后都要连接到原生方法forName0().
而三个参数的forName(),最后调用的是: forName0(name, initialize, loader); 不管使用的是new 來实例化某个类、或是使用只有一个参数的Class.forName()方法,内部都隐含了“载入类 + 运行静态代码块”的步骤。 而使用具有三个参数的Class.forName()方法时,如果第二个参数为false,那么类加载器只会加载类,而不会初始化静态代码块,只有当实例化这个类的时候,静态代码块才会被初始化,静态代码块是在类第一次实例化的时候才初始化的。 (3)
直接使用类加载器
1)获得对象所属的类 : getClass()方法
2)获得该类的类加载器 : getClassLoader()方法 (4) 实例一:
JAVA中类文件加载是动态的。也就是说当我们用到的时候才会去加载,如果不用的话,就不会去加载我们的类。
JAVA为我们提供了两种动态机制。第一种是隐式机制。第二种是显示机制。如下:
两种方法:
|
+-- 隐式机制 :new一个对象 + 调用类的静态方法
|
+-- 显式机制 :
|
+-- 由 java.lang.Class的forName()方法加载
|
+-- 由 java.lang.ClassLoader的loadClass()方法加载 (2)使用Class.forName()
Class.forName()方法具有两个形式:
+- public static Class forName(String className)
|
+- public static Class forName(String className, boolean initialize,ClassLoader loader)
参数说明:
className - 所需类的完全限定名 (必须包含包名,否则出错!)
initialize - 是否必须初始化类 (静态代码块的初始化)
loader - 用于加载类的类加载器
调用只有一个参数的forName()方法等效于 Class.forName(className, true, loader)。
这两个方法,最后都要连接到原生方法forName0().
而三个参数的forName(),最后调用的是: forName0(name, initialize, loader); 不管使用的是new 來实例化某个类、或是使用只有一个参数的Class.forName()方法,内部都隐含了“载入类 + 运行静态代码块”的步骤。 而使用具有三个参数的Class.forName()方法时,如果第二个参数为false,那么类加载器只会加载类,而不会初始化静态代码块,只有当实例化这个类的时候,静态代码块才会被初始化,静态代码块是在类第一次实例化的时候才初始化的。 (3)
直接使用类加载器
1)获得对象所属的类 : getClass()方法
2)获得该类的类加载器 : getClassLoader()方法 (4) 实例一:
//example 2.1
// Zoo.java
abstract class Animal {
static {
System.out.println("Animal static code block ");
}
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 {
public static void main(String [] args)throws Exception {
System.out.println("new Zoo before");
Zoo z = new Zoo();
Class c = Class.forName("Dog",false,z.getClass().getClassLoader());
System.out.println("initilize before ");
Animal dog = (Animal)c.newInstance();
System.out.println("new Zoo after ");
}
}
输出如下:
[loaded Zoo from fiel:/E:/java/pritice]
new Zoo before
[loaded Animal from fiel:/E:/java/pritice]
[loaded Dog from fiel:/E:/java/pritice]
initilize before
Animal static code block
Animal constructor
Dog Constructor
new Zoo after
从 上图可以看出来类加载完成后并没有立即执行静态初始化代码,而是到了实例化的时候才进行了静态初始化。有时候我们会说静态代码是在类第一次被加载时执行 的,并且只执行一次。其实这是对与new一个对象,第一次访问类的静态代码以及第二个参数为true时而言的,对于动态的加载来说,如果 forName方法的第二个参数设置为false,那么就是在实例化的时候才会执行静态初始化。当然默认情况下第二个参数是true.
(5) 实例二:
// Zoo.java
abstract class Animal {
static {
System.out.println("Animal static code block ");
}
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 {
public static void main(String [] args)throws Exception {
System.out.println("new Zoo before");
Zoo z = new Zoo();
Class c = Class.forName("Dog",false,z.getClass().getClassLoader());
System.out.println("initilize before ");
Animal dog = (Animal)c.newInstance();
System.out.println("new Zoo after ");
}
}
输出如下:
[loaded Zoo from fiel:/E:/java/pritice]
new Zoo before
[loaded Animal from fiel:/E:/java/pritice]
[loaded Dog from fiel:/E:/java/pritice]
initilize before
Animal static code block
Animal constructor
Dog Constructor
new Zoo after
从 上图可以看出来类加载完成后并没有立即执行静态初始化代码,而是到了实例化的时候才进行了静态初始化。有时候我们会说静态代码是在类第一次被加载时执行 的,并且只执行一次。其实这是对与new一个对象,第一次访问类的静态代码以及第二个参数为true时而言的,对于动态的加载来说,如果 forName方法的第二个参数设置为false,那么就是在实例化的时候才会执行静态初始化。当然默认情况下第二个参数是true.
(5) 实例二:
package test;
import java.util.Vector;
class Atest
{
public void print()
{
System.out.println("use A ...");
try {
Class cc=Class.forName("test.Btest");
Btest bt = (Btest)cc.newInstance();
bt.print();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Btest
{
public void print()
{
System.out.println("use B ...");
}
}
public class Test {
public static void main(String[] args) {
//OK
try {
Test test=new Test();
Class a=Class.forName("test.Atest",false,test.getClass().getClassLoader()); System.out.println("---"+a);
Atest aa=(Atest)a.newInstance();
System.out.println("---"+aa);
aa.print();
} catch (Exception e) {
e.printStackTrace();
}
//OK
// try {
// Test test=new Test();
// ClassLoader loader=test.getClass().getClassLoader(); //也可
// ClassLoader loader=Test.class.getClassLoader();
// Class a=loader.loadClass("test.Atest");
// Atest aa=(Atest)a.newInstance();
// System.out.println("---"+aa);
// aa.print();
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}
输出结果是: ---class test.Atest
---test.Atest@757aef
use A ...
use B ... 可见,使用Class.forName()或ClassLoader.loadClass(),得到的只是class.如上输出.要生成对象,还须实例化.
import java.util.Vector;
class Atest
{
public void print()
{
System.out.println("use A ...");
try {
Class cc=Class.forName("test.Btest");
Btest bt = (Btest)cc.newInstance();
bt.print();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Btest
{
public void print()
{
System.out.println("use B ...");
}
}
public class Test {
public static void main(String[] args) {
//OK
try {
Test test=new Test();
Class a=Class.forName("test.Atest",false,test.getClass().getClassLoader()); System.out.println("---"+a);
Atest aa=(Atest)a.newInstance();
System.out.println("---"+aa);
aa.print();
} catch (Exception e) {
e.printStackTrace();
}
//OK
// try {
// Test test=new Test();
// ClassLoader loader=test.getClass().getClassLoader(); //也可
// ClassLoader loader=Test.class.getClassLoader();
// Class a=loader.loadClass("test.Atest");
// Atest aa=(Atest)a.newInstance();
// System.out.println("---"+aa);
// aa.print();
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}
输出结果是: ---class test.Atest
---test.Atest@757aef
use A ...
use B ... 可见,使用Class.forName()或ClassLoader.loadClass(),得到的只是class.如上输出.要生成对象,还须实例化.
相关阅读 更多 +