(一)JAVA反射机制学习及研究

1,摘要

Java反射机制是java是动态语言的一个标志.同时其为java动态代理和远程调用提供了实现的基础.本文先阐述了java反射机制的理论基础,然后以一个实例来进一步的说明.在此基础上,对java动态代理和远程调用,从理论研究到实际应用进行了深入的研究.

2,组织结构

        本文的组织结构如下:

        <1>Java反射机制研究.

        <2>Java动态代理

        <3>Java远程调用

3,Java反射机制研究

<1>理论基础

        Java是一种面向对象的编程语言,java将一切事物均视为对象.java可以在编译时和运行时两种情况下来获取一个对象的类型.java反射机制是java程序在运行时获取对象类型的一种方法,这就使Java具备一定的扩展性和动态性.

        我们先从jvm说起。Jvm是java语言最核心的内容,使java运行和具有跨平台特性的根源所在。我们编写的java文件,先由编译器编译为二进制的字节码。Jvm启动后,先运行类加载器(bootstrap classloader),由类加载器依次加载java核心api,扩展的第三方api,然后加载java的二进制字节码(.class文件),这时就开始运行java程序了。因此,在编译时我们可以定义一个对象的类型,如:Car t1 = new Car();其中Car为一个类。知道了该对象的类型,那么就可以执行该对象的相应方法了。然而,事物不是一成不变的,动态的事物才更精彩。接上,当Car的对象t1执行时,突然出现了一个新的需求,需要一个Plane类的对象来接着执行一些操作。此时,运行着的jvm不可能停下来,然后再从头来一次,毕竟射出去的箭嘛。另外,如果一个对象的引用已经被加载到了jvm中(注意是对象的引用而不是对象的实例,对象引用的解释见批注【1】),我需要获取这个对象的信息。因此,反射机制应运而生了。

        Java反射机制就是jvm在运行时,获取一个对象的一些属性信息,如该类的成员变量、方法、构造函数等,从而可以对这个类执行一些操作(就像这个类已经加载了一样)。或许这时,你能体会到反射机制的重要作用了,没有反射机制,java语言会是一潭死水!当然反射机制不仅仅是这么点作用,后续文章中会介绍其更伟大的作用,如动态代理、远程方法调用(RMI)等。

        那么我们就来认识一下java反射机制吧。在javaAPI中,反射机制存在于java.long目录下。具体的不必多说,请参考该目录下的Class类,和java.long.reflect目录相关信息。那么怎么使用如此重要的java反射机制呢?下面将一一进行说明。

<2>方法论

       通过对<1>的了解,我们大概知道反射机制大概有两种应用背景:1)jvm中只加载了一个类的对象的引用;2)jvm中没有加载类的任何信息。对于1),比较好办,既然该对象的引用存在于jvm中,那么我们获取它的类型吧,获得了对象的类型,那么就可以通过Class类提供的一些方法得到该类型的属性信息了,进而可以利用java反射机制提供的一些方法来修改、执行该类的成员属性和方法了。对于2),稍微有点麻烦,不过并不复杂,既然这个类一点信息都没有加载到jvm,那只好先把这个类的信息加进来了,一个十分重要的前提是:这个类编译后的.class文件必须存在,并且位于jvm默认目录下。有了这个前提,我们先用Class.forName(“.class文件名称”);加载一下,然后就和1)差不多了。

<3>应用实例

1)jvm加载了类的对象的引用

package reflection;

publicclass TestReflectionUser {

   privateString id;

   privateString name;

   publicString getId() {

      returnid;

   }

   publicvoid setId(String id) {

      this.id = id;

   }

   publicString getName() {

      returnname;

   }

   publicvoid setName(String name) {

      this.name = name;

   }

  

}


表1 测试类

 

package reflection;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

publicclass TestReflection {

   /**

    * 测试反射机制1

    * @throws Instantiation Exception

    * @throws IllegalAccessException

    */

   publicvoid doTest()throws InstantiationException, IllegalAccessException{

      //得到TestReflectionUser的一个对象的引用,此时并没有实例化。

      Class c2 = TestReflectionUser.class;

      //获取该对象的引用所指向的类名

      System.out.println("the c2 class name"+c2.getName());

      //获取该类的成员变量

      Field[] fields = c2.getDeclaredFields();

      System.out.println("the c2 fields length"+fields.length);

      //获取该类的成员方法

      Method[] methods = c2.getMethods();

      System.out.println("the c2 methods length"+methods.length);

      //获取该类的一个实例

      TestReflectionUser user = (TestReflectionUser)c2.newInstance();

      user.setName("test user");

      System.out.println("the instance user's name"+user.getName());      

   }

   publicstaticvoid main(String[] args)throws InstantiationException, IllegalAccessException{

      //获得TestReflection的一个对象实例

      TestReflection tr = new TestReflection();

      tr.doTest();

   }

}

 

表2 测试反射机制1

上例中,由于java文件中有“Class c2 = TestReflectionUser.class;”,因而随着编译和jvm的加载,TestReflectionUser的一个对象的引用已经被加载了。

下面,我们来看看第二种反射机制的运用形式。

2jvm没有加载该类的任何信息

   在示例之前,先要对java.long.Class中的

public static Class<?>forName(String className)throwsClassNotFoundException

方法进行说明。按java API的说法,执行该方法相当于执行了

publicstatic Class<?>forName(String name,boolean initialize,                             ClassLoader loader)throwsClassNotFoundException

这个方法,这个类的作用就是“给定一个类或接口的完全限定名,此方法会试图定位、加载和链接该类或接口”。因而这个当我们知道一个类的名字的时候,使用该方法可以将该类加载到jvm中。

package reflection;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

publicclass TestReflection {

   /**

    * 测试反射机制2

    * @throws ClassNotFoundException

    * @throws InstantiationException

    * @throws IllegalAccessException

    */

   publicvoid doTest()throws ClassNotFoundException, InstantiationException, IllegalAccessException{

      //得到TestReflectionUser的一个对象的引用,此时并没有实例化。

      Class c2 = Class.forName("reflection.TestReflectionUser");

      //获取该对象的引用所指向的类名

      System.out.println("the c2 class name"+c2.getName());

      //获取该类的成员变量

      Field[] fields = c2.getDeclaredFields();

      System.out.println("the c2 fields length"+fields.length);

      //获取该类的成员方法

      Method[] methods = c2.getMethods();

      System.out.println("the c2 methods length"+methods.length);

      //获取该类的一个实例

      TestReflectionUser user = (TestReflectionUser)c2.newInstance();

      user.setName("test user");

      System.out.println("the instance user's name"+user.getName());       

   }

   publicstaticvoid main(String[] args)throws InstantiationException, IllegalAccessException, ClassNotFoundException{

      //获得TestReflection的一个对象实例

      TestReflection tr = new TestReflection();

      tr.doTest();

   }

}

 

表3 反射机制2

 

我们发现,与1)相比,唯一的不同是“Class c2 = Class.forName("reflection.TestReflectionUser");虽然差别很小,但由于具体的运行原理有些不同,因而分开进行了说明。

<4>总结

        Java反射机制是java的一个重要的特性。有了反射机制Java看起来才更具备一个动态语言的特征。本文先从jvm的类加载机制说起,从而引出了Java反射机制的重要性和必要性,顺便也点出了Java反射机制的两种使用背景。最后分两种情况对反射机制的使用方法进行了阐述。

<5>后记

        Java反射机制的使用绝不仅仅是这么点,在java其他的技术,如动态代理、远程方法调用等,以及一些java框架和web中间件中都有应用。接下来,会在此文的基础上一一进行介绍。同时,若是文中有什么错误,还请大侠们指正。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值