新疆软件开发

本站首页 软件开发 成功案例 公司新闻 公司简介 客服中心 软件技术 网站建设
  您现在的位置: 新疆二域软件开发公司 >> Java技术 >> 文章正文

JAVA程序类加载及其反射机制

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对象来进行动态装载类的。

作者:佚名 | 文章来源:赛迪网 | 更新时间:2007-10-22 10:10:32

  • 上一篇文章:

  • 下一篇文章:

  • 相关文章:
    JAVA开发的6个实践的例子
    JAVA中的抽象类型的一些概念
    java语言开发程序中的几个例子大家看看
    了解java开发语言在软件开发中的几个误区
    如何才能使用Java实现内部领域的特定语言
    Java开发学习小心使用Date以及Time类
    sun最近修补了一部分java的安全补丁
    Java程序员应该了解那些开源协议
    java性能优化的一些见解
    解析c#语言和java语言最相似的地方
    软件技术
    · 开发语言
    · Java技术
    · .Net技术
    · 数据库开发
    最新文章  
    ·j2se 嵌入式脚本抓取引擎
    ·JAVA开发的6个实践的例子
    ·JBuilder7 / Weblogic7开发
    ·JAVA中的抽象类型的一些概
    ·java语言开发程序中的几个
    ·了解java开发语言在软件开
    ·如何才能使用Java实现内部
    ·Java开发学习小心使用Date
    ·Java程序员应该了解那些开
    ·java性能优化的一些见解
    ·介绍JDK5.0一些collection
    ·基础学习:java中使用存储
    ·解析c#语言和java语言最相
    ·Java语言学习:jAVA中 的多
    ·Java是不是应该增加新特性
    关于我们 | 软件开发 | 下载试用 | 客服中心 | 联系我们 | 友情链接 | 网站地图 | 新疆电子地图 | RSS订阅
    版权所有 © 2016 新疆二域软件开发网 www.k8w.net All Rights Reserved 新ICP备14003571号
    新疆软件开发总机:0991-4842803、4811639.
    客服QQ:596589785 ;地址:新疆乌鲁木齐北京中路华联大厦A-5C 邮编:830000