Java反射机制(Reflection)

        Reflection也就是反射,是Java语言的一个重要特征,我们知道,在使用一个类之前,我们往往都已经创建好它了,比如创建一个类文件,然后再写些属性、方法等,也就是这种类是静态的,但反射机制却允许你动态地创建一个类。除了动态地创建一个类外,我们还能动态地获取同类对象的数据,并将这些数据赋给新创建的类,这有点类似克隆复制。在很多时候,我们都需要这种动态创建类的特征,比如在处理一些业务,但这些业务却又稍有区别的时候,往往对应着多个类,在处理的时候,我们就要根据不同的业务处理来调用不同的类,这个时候反射机制就派上用场了。


JAVA反射机制是:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。


        一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
        尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。


以下是JDK API中关于软件包java.lang.reflect的描述
        提供类和接口,以获取关于类和对象的反射信息。在安全限制内,反射允许编程访问关于加载类的字段、方法和构造方法的信息,并允许使用反射字段、方法和构造方法对对象上的基本对等项进行操作。
如果必需的 ReflectPermission 可用,则 AccessibleObject 允许抑制访问检查。
Arrays 提供动态创建和访问数组的静态方法。
        此包中的类以及 java.lang.Class 可以适应以下应用程序的需要:调试程序、解释程序、对象检查程序、类浏览程序,以及服务(比如,Object Serialization 和 JavaBean,它们需要访问目标对象(基于其运行时类)的公共成员或给定类声明的成员)。


下面通过两个简单例子来说明反射的用法,首先先创建一个Person类:

package test;

public class Person {

private int age;
private String name = "";
private String[] arr = new String[2];

public Person(){}

public Person(String name,int age){
this.name = name;
this.age = age;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String[] getArr() {
return arr;
}

public void setArr(String[] arr) {
this.arr = arr;
}

}


实例1:得到Person类的属性及方法信息

private static void testSimpleReflect(){
    String className = "test.Person";
    try {
        Class c = Class.forName(className);
        Field[] fields = c.getDeclaredFields();
        Method[] m = c.getDeclaredMethods();
    for (Field field : fields){
        System.out.println(field.getName());
   }
    for (Method method : m){
        System.out.println(m.getClass());
    }
   } catch (ClassNotFoundException e) {
        e.printStackTrace();
  }
}


这种是非常简单的,通过类所在包路径来得到一个类,在实际的工作中,也是使用最多的。

实例2:对象复制
//注:下面这段代码copy方法来源于其他地方,见:
//http://wishlife.iteye.com/blog/209885
@SuppressWarnings("unchecked")
public static Object copy(Object object) throws Exception {
// 获得对象类型
Class classType = object.getClass();
    System.out.println("" + classType.getName()); // 通过默认构造方法创建一个新的对象
    Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {}); // 获得对象的所有属性
    Field fields[] = classType.getDeclaredFields();
    for (int i = 0; i < fields.length; i++) {
        Field field = fields[i];
        String fieldName = field.getName();
        String firstLetter = fieldName.substring(0, 1).toUpperCase(); // 获得和属性对应的getXXX()方法的名字
        String getMethodName = "get" + firstLetter + fieldName.substring(1); // 获得和属性对应的setXXX()方法的名字
        String setMethodName = "set" + firstLetter + fieldName.substring(1); // 获得和属性对应的getXXX()方法
        Method getMethod = classType.getMethod(getMethodName,
        new Class[] {}); // 获得和属性对应的setXXX()方法
        Method setMethod = classType.getMethod(setMethodName,

   new Class[] { field.getType() }); // 调用原对象的getXXX()方法
      Object value = getMethod.invoke(object, new Object[] {});
      System.out.println(fieldName + ":" + value); // 调用拷贝对象的setXXX()方法
      setMethod.invoke(objectCopy, new Object[] { value });
}
return objectCopy;
}
 
 
 
 


        利用反射来实现对象的复制,我们通常不用自己这么干,因为开源系统BeanUtils已经替我们做好对象拷贝的封装了,我们直接调用它的方法即可,但值得注意的是,BeanUtils也是基于反射机制来做的封装,这方面可以参见:http://www.zihou.me/2011/03/19/2905

下面是一调用:

public static void main(String[] args){
    Person person = new Person("tom",22);
    String[] strs = new String[]{"a","b"};
    person.setArr(strs);
    try {
        Person p = (Person)copy(person);
        System.out.println(p.getName()+">>"+p.getAge());
        for (String str : p.getArr()){
            System.out.println(str);
      }
    } catch (Exception e) {
        e.printStackTrace();
  }
//        testSimpleReflect();
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值