`
jacklan
  • 浏览: 134509 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA程序类的加载及其反射机制全面介绍

阅读更多
JAVA程序类的加载及其反射机制全面介绍
发布时间:2007.11.02 04:47     来源:赛迪网技术社区    作者:baocl

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


原文:http://java.ccidnet.com/art/3539/20071101/1261327_1.html
分享到:
评论

相关推荐

    基于反射机制的Java编程题自动评分技术.pdf

    使用Java反射机制,评分系统可以访问到类的私有成员和方法,甚至可以动态加载和调用类,这种能力为动态测试提供了基础。在此基础上,结合静态分析的代码结构检查,系统可以实现对代码质量的全面评估。 本技术的优点...

    Java自省类教程

    本文将深入探讨Java反射机制及其应用。 首先,我们需要理解几个关键概念: 1. **Class对象**:每个Java类在内存中都有一个对应的Class对象,这个对象包含了类的所有信息。我们可以通过`Class.forName()`方法或`类名...

    java程序设计进阶版

    4. **反射机制**:Java反射机制允许程序在运行时动态获取类的信息并操作对象,包括Class类的使用、构造器、方法和字段的调用,以及动态代理的实现。 5. **异常处理**:理解如何正确地使用try-catch-finally语句,...

    java 反射 报错 no such method exception

    ### Java反射机制与NoSuchMethodException详解 在Java编程中,反射是一种强大的机制,允许程序在运行时检查和修改自身结构和行为。然而,当开发者尝试使用反射调用一个不存在的方法时,便会遇到`java.lang....

    《JAVA语言程序设计》期末考试试题及答案_java期末考试_java_

    8. **反射机制**:通过Class类获取类的信息,动态创建对象,调用方法,修改字段值。反射是Java的一个强大功能,常用于框架开发。 9. **Java API的使用**:如Math类的数学运算,日期时间API,正则表达式,XML解析等...

    Java程序设计技巧与开发实例

    最后,Java的反射机制允许程序在运行时动态访问类的信息,如类名、属性和方法,这在插件系统和元编程中非常有用。但需要注意的是,过度使用反射可能会影响程序的性能和安全性。 总之,“Java程序设计技巧与开发实例...

    Java2程序设计教程(第二版)

    2. **平台无关性**:Java程序可以在任何安装了Java虚拟机(JVM)的平台上运行,无需重新编译。 3. **安全性和健壮性**:Java通过严格的类型检查、异常处理机制等手段确保程序的安全性和稳定性。 4. **多线程**:Java...

    反射机制方面的资料学习(自己整理)

    反射机制的核心在于Java.lang.reflect包中的类,如Class、Constructor、Method和Field等,它们提供了对Java类及其组件的动态访问能力。本资料集合包含了对反射机制的深入理解和实践应用。 1. **什么是反射**: ...

    Java程序设计实用教程(第4版)[叶核亚]

    《Java程序设计实用教程(第4版)》是由叶核亚编著的一本经典Java学习教材,这本教程深入浅出地介绍了Java编程语言的基本概念和技术。教程内容丰富,不仅包含理论知识,还提供了大量的实例和习题解答,旨在帮助读者...

    《Java程序设计与应用》

    《Java程序设计与应用》是一本深入探讨Java编程语言及其应用的教材,旨在帮助学习者掌握Java编程的基础知识,理解其核心概念,并能熟练应用于实际项目中。这本书涵盖了从简单的语法结构到高级特性的全面讲解,是初学...

    Java语言程序设计基础篇全部源代码

    10. **反射**:Java的反射机制允许在运行时动态地获取类的信息并操作类的对象,是许多高级功能如插件机制、元编程的基础。 11. **Java集合框架**:Java集合框架是Java库的重要组成部分,包括List、Set、Map等接口...

    java面试题总汇《很经典的》

    12. **反射与注解**:Java反射机制允许程序在运行时动态访问类的信息,注解则为代码提供了元数据,这两者在实际开发中都有广泛应用。 13. **并发编程**:Java并发库提供了丰富的工具,如ExecutorService、Future、...

    Java高级程序设计期末试卷

    7. **反射机制**:通过Class对象动态访问类的信息,创建对象,调用方法,以及修改字段值。反射在插件化、序列化、动态代理等方面有广泛应用。 8. **设计模式**:例如单例模式、工厂模式、观察者模式等,这些设计...

    Java程序设计(2010年)

    16. **Java反射机制**:介绍如何在运行时动态获取类的信息并调用其方法,以及Class类和反射API的使用。 17. **Java内存管理**:垃圾收集机制、内存区域划分(堆、栈、方法区等)以及内存泄漏问题。 18. **JVM原理*...

    JAVA REFLECTION IN ACTION

    书中不仅介绍了反射的基本概念,还深入探讨了诸如代理、类加载等更高级的主题,这些都是在日常Java程序中经常遇到但往往没有得到充分解释的部分。 #### 实践应用与案例分析 本书通过一系列精心设计的例子,展示了...

    关于Java编程特点及其技术分析.zip

    8. **反射机制**:Java反射机制允许程序在运行时动态获取类的信息并操作对象,增强了程序的灵活性。 9. **泛型**:Java的泛型引入了类型参数,提高了代码的类型安全性和重用性。 10. **模块系统**:Java 9引入的...

    Java程序设计研究与实践-理论和实践.zip

    本资源“Java程序设计研究与实践-理论和实践.zip”包含了一份深入探讨Java编程的PDF文档,旨在帮助读者从理论到实践全面掌握Java语言。 理论部分,主要涵盖了以下几个关键知识点: 1. **Java语言基础**:包括Java...

    软件工程_Java程序设计_课件

    9. **Java程序设计进阶**:`java程序设计34.ppt`和`java程序设计1.ppt`可能涉及更高级的主题,如设计模式、集合框架、反射、注解、泛型等,这些都是Java开发者必备的技能。 这些课件为学习者提供了一个全面的Java和...

    使用java理解程序逻辑

    10. **反射(Reflection)**:Java反射机制允许在运行时动态访问和修改类的信息。虽然高级,但理解反射可以帮助实现元编程,增强程序的灵活性。 11. **JVM(Java虚拟机)**:理解JVM的工作原理,包括类加载、内存...

Global site tag (gtag.js) - Google Analytics