Chinaunix首页 | 论坛 | 博客
  • 博客访问: 367168
  • 博文数量: 132
  • 博客积分: 3066
  • 博客等级: 中校
  • 技术积分: 781
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-14 16:19
文章分类

全部博文(132)

文章存档

2012年(1)

2010年(50)

2009年(81)

我的朋友

分类: Java

2010-06-10 12:51:50

(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)
实例一:
//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)
实例二:
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

use A ...
use B ...
 
可见,使用Class.forName()或ClassLoader.loadClass(),得到的只是class.如上输出.要生成对象,还须实例化.
阅读(3227) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

kkkkk6k2013-01-13 00:24:48

运行直接说是找不到类
new Zoo before
Exception in thread "main" java.lang.ClassNotFoundException: Dog
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
....

kkkkk6k2013-01-13 00:24:46

运行直接说是找不到类
new Zoo before
Exception in thread "main" java.lang.ClassNotFoundException: Dog
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
....

chinaunix网友2010-09-09 08:47:00

3q