当前位置:编程学习 > JAVA >>

Java背后的秘密之Java的类装载器

Java语言是一种先天具备动态性的语言,之所以具备动态性正是因为Java类装载器的存在。这会给我们开发带来革命性的变革,因为我们有可能开发出有弹性、易扩展的程序。从而大大增强我们程序的可维护性。按载入条件分为预先载入与按需载入。
1.通常基础类库需要预先载入。(常驻内存)
2.自定义类库需要按需载入。(使用时载入,使用完毕时由垃圾收集器负责释放)

类装载器运行模式分为两种,如下图:

 \

1.使用new关键字来隐式加载,首先来看一个例子:直接上代码,很简单的三个类。
        [java]
public class A { 
    public void print() { 
        System.out.println("Using class A"); 
    } 

public class A {
 public void print() {
  System.out.println("Using class A");
 }
}[java] view plaincopyprint?public class B { 
    public void print() { 
        System.out.println("Using class B"); 
    } 

public class B {
 public void print() {
  System.out.println("Using class B");
 }
}[java] view plaincopyprint?public class Main { 
    public static void main(String[] args) { 
        A a = new A(); 
        a.print(); 
        B b = new B(); 
        b.print(); 
    } 

public class Main {
 public static void main(String[] args) {
  A a = new A();
  a.print();
  B b = new B();
  b.print();
 }
}运行结果如下:

\
但是我们如果需要看类加载的详细内容,我们就要用到这条命令:java -verbose:class Main

\
看看上图是不是首先载入的Java的基础类库,看最后几行,首先加载Main,接下来实例化A类的时候会加载A,调用a.print()的时候打印了Using class A,然后加载B类,执行B中的方法。

2.使用Class.forName()方法载入类,这个做过J2EE开发的应该知道,在数据库连接加载驱动的时候都可以这么加载。还是看一个简单的例子:
[java]
public interface Office { 
    void start(); 

public interface Office {
 void start();
}[java] view plaincopyprint?public class Word implements Office { 
    public void start() { 
        System.out.println("Word start"); 
    } 

public class Word implements Office {
 public void start() {
  System.out.println("Word start");
 }
}[java] view plaincopyprint?public class Excel implements Office { 
    public void start() { 
        System.out.println("Excel start"); 
    } 

public class Excel implements Office {
 public void start() {
  System.out.println("Excel start");
 }
}[java] view plaincopyprint?public class Main { 
    public static void main(String[] args) throws Exception{ 
        Class c = Class.forName(args[0]); 
        Object o = c.newInstance(); 
        Office office = (Office) o; 
        office.start(); 
    } 

public class Main {
 public static void main(String[] args) throws Exception{
  Class c = Class.forName(args[0]);
  Object o = c.newInstance();
  Office office = (Office) o;
  office.start();
 }
}继续看一下加载的详细内容:

\
详细观察一下最后几行载入的顺序,看看是否跟我们程序执行的是一样的呢?
此处有一个结论:Java类装载器会按照继承体系从上至下的依次载入类,直到所有的祖先类都载入(上例中是接口),才轮到自己;相反,在Java类对象实例被收集释放时,顺序与载入相反。由此,我们也能看出,Java类的继承体系不宜过长,因为那样会使类的载入与释放的性能受到影响。

3.直接使用类装载器ClassLoader,例子是上一个例子的改版,只是修改了Main.java,其他三个类不变。
[java]
public class Main { 
    public static void main(String[] args) throws Exception { 
        System.out.println("begin load"); 
        // Main main = new Main();  
        // ClassLoader loader = main.getClass().getClassLoader();  
        ClassLoader loader = Main.class.getClassLoader(); 
        Class c = loader.loadClass(args[0]); 
        System.out.println("begin init"); 
        Object o = c.newInstance(); 
        Office office = (Office) o; 
        office.start(); 
    } 

public class Main {
 public static void main(String[] args) throws Exception {
  System.out.println("begin load");
  // Main main = new Main();
  // ClassLoader loader = main.getClass().getClassLoader();
  ClassLoader loader = Main.class.getClassLoader();
  Class c = loader.loadClass(args[0]);
  System.out.println("begin init");
  Object o = c.newInstance();
  Office office = (Office) o;
  office.start();
 }
}首先获得ClassLoader的实例,有两种方法,上面注释的为一种,放开的为另一种。然后调用loadClass()方法。运行一下,看下效果:

 \
\

怎么样,Java语言够动态吧。


 

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,