zoukankan      html  css  js  c++  java
  • 浅谈Java反射机制

    反射库(reflection library )提供了一个功能强大的工具集,一遍编写可以动态操纵java代码的程序。这种功能被大量用在javaBeans中(java组件的体系结构)。使用反射,java可以支持vb用户习惯使用的工具,特别是在设计或运行时添加新类时,可以快速应用开发工具动态查询新添加类的能力。

    能够分析类能力的程序称为反射(refletive)。反射机制可以用来:

    l  在运行时分析类的能力

    l  在运行时查看对象,例如编写toString方法供所有类使用。

    l  实现通用的数组操作代码

    l  利用method对象,该对象很像C++中的函数指针

    1.Class类

    在程序运行期间java运行时系统始终未所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。

    我们可以通过专门的java类来访问这些信息。保存这些信息的类被称为Class,Object类中的getClass方法会返回一个Class类型的实例(即返回该对象所属的类,包括包名)。

    例如 Employee  e=null;

            Class c1=e.getClass();

            String name=c1.getName();

    将会打印出 Employee

    还可以通过Class的静态方法forName获得类名对应的Class对象

            String className=”java.util.Random”;

            Class c1=Class.forName(className);

    获得Class类对象的第三种方法:如果T是任意的java类型(或void关键字),T.class将代表匹配的类对象

    Class c1=Random.class;//假设java.uitl.Random类已导入

    Class c2=int.class;

    Class c3=Double[].class;

    注意:一个Class对象实际表示一个类型,而这个类型不一定是一种类,int不是类,但int.class是一个Class类型的对象

                虚拟机为每个类型管理一个Class对象,因此可以用==运算符实现两个类对象比较操作:

    例如if(e.getClass()==Employee.class)…

                 还有一个很有用的方法newInstance,可以动态创建一个类的实例,例如:

               Employee eCopy= e.getClass().newInstance();

          创建了一个与e具有相同类类型的实例,newInstance方法调用默认的构造器初始化新创建的对象,如果该类没有摩恩构造器会抛出异常

    String s=”java.util.Random”;

    Object o=Class.forName(s).newInstance();

    如果需要一个有参构造对象,必须用Constructor类中的newInstance方法了

    2利用反射的分析类的能力

             反射机制最重要的内容—检查类的结构

             在java.lang.reflect包中有三个类:Field,Method,Constructor分别用于描述类的域,方法和构造器,这三个类都有一个叫做getName方法,用来返回项目的名称。Field有个getType方法返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method类还可以有能报告返回类型的方法,这三个类还有一个叫做getModifiers的方法,它将返回一个整形数值,用不同的位开关描述public和static这样的修饰符使用状况,另外,还可以利用java.lang.reflect包中的Modifier类的静态方法分析getModifiers返回的整数数值。例如可以使用Modifier类中的isPublic,isPrivate或isFinal判断方法或构造器是否是public,private,final。我们需要做的uanu工作就是要调用Modifier类的相关方法,对返回的整型数值进行发内心。另外还可以利用Modifier.toString 方法将修饰符打印出来

             Class类中的getFields,getMethods和getConstructors方法将分别返回类提供的public域,方法和构造器数组,其中包括超类的宫欧处呢雇员。Class类的getDeclaredFields,getDeclaredMethods和getDeclaredConstructors方法将分别返回类中声明的全部域,方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员

         3在运行时使用反射分析对象

    前一节知道如何查看任意对象的数据域名称和类型:

    l  获取对应的Class对象

    l  通过Class对象调用getDeclaredFields

    本节进一步查看数据域的实际内容,利用反射机制可以查看在编译时还不清楚的对象域。

    查看对象域的关键方法是Field类中的get方法,如果f是一个Field类型的对象,object是某个包含f域的类的对象,f.get(obj)将返回一个对象,其值为obj域的当前值

    Employee  harry=new Employee(“harry_potter”,3500,1,12,1998);

    Class c1=harry.getClass();

    Field f=c1.getDeclaredField(“name”);

    Object v=f.get(harry);

    有两个问题:

    ①  对象域中某个属性的访问权限如果不是public如何获取值

    ②  属性的类型如果不是引用类型而是基本数据类型如何获取

    问题①,如果属性是私有域或者保护域,会抛出IllegalAccessException异常,只有利用该属性的get方法才可以访问到属性值。除非拥有访问权限,否则java安全机制只允许查看任意对象有哪些域,而不允许读取他们的值。

             反射机制的默认行为受限于java访问控制。然而,如果一个java程序没有受到安全管理器控制,就可以覆盖访问控制。可以调用Method,Constructor,Field对象的setAcessible方法:

             f.setAccessible(true);

    Object v=f.get(harry);//now is OK

    setAccessible 方法是AccessibleObject类中的一个方法,他是Filed,Method,Constructor类的公共超类,这个特性是为了调试,持久存储和相似机制提供的。

    问题②对于非引用类型的属性,可以调用相应的getInt,getDouble等对应方法返回基本类型的类型值,也可以直接用get方法,此时返回的是数据类型的包装类型。

    double salary=f.getDouble(harry);//ok

    Double salary=f.get(harry);//ok

             当然,可以获得就可以设置,调用相应的f.set(obj,value)可以将obj对象的f域设置为新值

    4使用反射编写泛型数组代码

    Java.lang.reflect包中的Array类允许动态创建数组,例如,可以将这个特性应用到Array类中的copyOf方法实现中,可以扩展已经填满的数组

  • 相关阅读:
    [算法] 堆栈
    [刷题] PTA 02-线性结构3 Reversing Linked List
    java IO流 (八) RandomAccessFile的使用
    java IO流 (七) 对象流的使用
    java IO流 (六) 其它的流的使用
    java IO流 (五) 转换流的使用 以及编码集
    java IO流 (四) 缓冲流的使用
    java IO流 (三) 节点流(或文件流)
    java IO流 (二) IO流概述
    java IO流 (一) File类的使用
  • 原文地址:https://www.cnblogs.com/gaochaochao/p/8335547.html
Copyright © 2011-2022 走看看