网站首页
JSP空间
动态资讯
开源项目
技术文档
资源下载
J2EE资源
客户论坛
在线支付
 
  技术文档>>JAVA>>新手入门>>基础入门>查看文档  
  新手看招:java程序的类加载及其反射机制     
  文章作者:未知  文章来源:赛迪网技术社区  
  查看:60次  录入:管理员--2007-11-16  
 

java中类文件加载是动态的。jvm指令是被封装在了. class文件里面,而.class文件的加载过程是动态的,也就是说当我们用到的时候才会去加载,如果不用的话,就不会去加载我们的类。这里所说的用到包括两种方式,第一种就是new一个对象的时候(这个时候要特别注意,当设计到多态的时候,就会有一点点变化,这时候编译器会做一些优化,这样以来当加载的时候会提前加载设计到多态的类,关于这一点下面有个例子(example 1)来说明。另一种就是当一个类的静态代码被调用的时候。

java 代码

//example 1
// zoo.java

abstract class animal {

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 {

private animal am; //example 1.1
//private dog am; example 1.2
private tiger tiger;

zoo(){
tiger = new tiger();
am = new dog();

}


public static void main(string [] args){

system.out.println("new zoo before");
zoo z = new zoo();
system.out.println("new zoo after ");

}
}



  当我们注释掉example.1.1行时,运行example1.2行,结果如下:

  example 1.2

  分析以上两图的运行结果我们可以看出:当我们将子类对象赋值给父类时,编译器会做一点优化,于是加载器在还没有new 子类对象的时候已经加载了父类以及子类(example1.1结果),当不存在多态的时候,我们可以看到是当要new dog()的时候才会加载dog以及父类。无论何种方式,在new之前,类确实已经加载到了内存中。

  java为我们提供了两种动态机制。第一种是隐式机制。其实new一个对象和调用类的静态方法时,就是隐式机制在工作。第二种是显示机制。显示的机制又有两种策略(第一种是用java.lang.class的forname(string str)方法,第二种是用java.lang.classloader的loadclass())。

  第一种:利用forname方法

  当我们查api文档就会发现forname方法有两种形式。分别如下:

public static class<?> forname(string classname) 
throws classnotfoundexception

public static class<?> forname(string name,
boolean initialize,
classloader loader)
throws classnotfoundexception



  先来说说第二种方法:第二个方法值得注意的就是第二个参数boolean initialize,如果我们把这个参数设置为false,那么当我们加载完类后就不会执行静态代码和静态的初始化动作。只有当我们new一个对象的时候才会初始化。而第三个参数是用来指明类的加载器的。

  如果查看java.lang.class类的源代码,上述两种方法最终都会调用class类中的私有的native方法forname0(),此方法的声明如下:

private static native class forname0(string name, boolean init , classloader loader) 
throws classnotfoundexception;


  所以当我们调用class.forname(name )时,其实是在方法内部调用了:

forname0(name, true, classloader.getcallerclassloader()); 

  当我们调用class.forname(name, initialize, loader )的时候,实际上此方法内部调用了:

forname0(name, initialize, loader); 


  下面看一个例子,如果方法中第二个参数为false的情况:

java 代码
//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 ");

}
}



  类加载完成后并没有立即执行静态初始化代码,而是到了实例化的时候才进行了静态初始化。有时候我们会说静态代码是在类第一次被加载时执行的,并且只执行一次。其实这是对与new一个对象,第一次访问类的静态代码以及第二个参数为true时而言的,对于动态的加载来说,如果forname方法的第二个参数设置为false,那么就是在实例化的时候才会执行静态初始化。当然默认情况下第二个参数是true.

  第二种方法:利用class对象获取的classloader装载。

  下面是一个简单的例子:

java 代码
//example 2.2
//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 {


class c = zoo.class;
classloader loader = c.getclassloader();
system.out.println("loader before");
class dog = loader.loadclass("dog");
system.out.println("instance before ");
animal an = (animal)dog.newinstance();

 

}
}



  loader完成以后并没有立即进行静态代码的执行。只有当newinstance()的时候才执行静态初始化,这和把public static class forname(string name, boolean initialize, classloader loader)的第二个参数指定为false的情况完全一样。其实每当我们写完一个编译单元以后就会得到一个.calss文件,这个文件中就包含了该类的class对象。jvm就是利用这个class对象来进行动态装载类的。

 
 
上一篇: 关于eclipse 3.0中的插件自动构建简介    下一篇: 详细介绍构建高性能j2ee应用的十个技巧
  相关文档
sun 发布 jaxp 1.3 维护文档草案 11-17
初探.net中的delegate类型与.net事件 11-17
利用easymock测试jdbc的过程详细解析 11-16
castor jdo: 一个欺诈的广告 11-17
java与xml联合编程之dom篇 11-17
自定义工具库 11-17
学习struts的好资料struts 11-17
java知识:class.forname的含义 11-20
浅谈 java 中 this 的使用 11-17
java加密枝术 11-17
java开发精彩教程:jsf系列(三) 11-16
对两代不同的corba对象生命周期的慨述 11-16
课程介绍(3)sl-265 结构化程序员的java技术 11-16
sun电信行业解决方案 11-17
c#使用hessian调用java的Ñ.. 11-17
java性能的优化(下)(转) 11-17
java网络编程基础 socket类的使用方法 11-16
使用java蓝牙无线通讯技术api概述之一 11-17
javaone2003:less hype more filling 11-17
web services开发体会和在项目中的教训 11-16
返回首页 | 关于我们 | J网章程 | JSP空间合租 | 客服中心 | 免责声明 | 常见问题 | 参观机房
本站主机空间代理至厦门市华众网络科技有限公司
《中华人民共和国增值电信业务经营许可证》
编号:闽B2-20050079
@2005-2008福建JSP技术网 版权所有 闽ICP备05000928号
技术电话:13616026886
邮箱:admin@fjjsp.com 站长QQ,点击这里给我发消息