Java 反射机制

 Java反射是Java语言的一个很重要的特征,它使得Java具有了“动态性”。

   一般而言,开发者社群说到动态语言,大致认同的一个定义 是:“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。

   Reflection是java被视为动态(或准动态)语言的一个关键性质。

 

Java反射机制主要提供了一下功能:

   1、在运行时判断任意一个对象所属的类。

   2、在运行时构造任意一个类的对象。

   3、在运行时判断任意一个类所具有的成员变量和方法。

   4、在运行时调用任意一个对象的方法。

 

在JDK中,主要由一下类来实现Java反射机制,这些类都位于java.lang.reflect包中:

   1、Class类:代表一个类

   2、Field类:代表类的成员变量(成员变量也称为类的属性)

   3、Method类:代表类的方法

   4、Constructor类:代表类的构造方法。

   5、Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

 

一、通过Class类获取成员变量、成员方法、接口,超类,构造方法等。

在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是ReflectionAPI中核心的类,它有以下方法

getName():获得类的完整名字

getFields():获得类的public类型的属性

getDeclaredFields():获得类的所有属性

getMethods():获得类的public类型的方法

getDeclaredMethods():获得类的所有方法

getMethod(String name,Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterType参数指定方法的参数类型。

getConstructors():获得类的public类型的构造方法。

getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterType参数指定构造方法的参数类型

newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

 

二、运行时复制对象

package reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTester {
    public Object copy(Object object) throws Exception {
        // 获得对象的类型
        Class<?> classType = object.getClass();
        System.out.println("Class:" + classType.getName());
        // 通过默认构造方法创建一个新的对象
        System.out.println("该类的构造方法有:"+classType.getConstructors()[0]);
        Object objectCopy = classType.getConstructor()
                .newInstance();
        // 获得对象的所有属性
        Field[] fields = classType.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            String fieldName = field.getName();
            System.out.println("fieldName:"+fieldName);
            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);
            System.out.println(fieldName + ":" + value);
            // 调用拷贝对象的setXXX()方法
            setMethod.invoke(objectCopy, new Object[] { value });
        }
        return objectCopy;
    }
    public static void main(String[] a) throws Exception {
        Customer customer = new Customer("Tom", 21);
        customer.setId(new Long(1));
        Customer customerCopy = (Customer) new ReflectTester().copy(customer);
        System.out.println(customerCopy==customer);
        System.out.println(customerCopy.equals(customer));
        System.out.println("Copy information:" + customerCopy.getId() + ""
                + customerCopy.getName() + "" + customerCopy.getAge());
    }
}
class Customer {
    private Long id;
    private String name;
    private int age;
    public Customer() {
    }
    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Long getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

解释:ReflectTester类的copy(object,object)方法依次执行以下步骤

(1)获得对象的类型

  Class classType=object.getClass();

  System.out.println("Class:"+classType.getName());

(2)通过默认构造方法创建一个新对象:

 Object objectCopy=classType.getConstructor().newInstance();

以上代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。

(3)获得对象的所有属性:

    Field[] fields=classType.getDeclaredFields();

    Class类的getDeclaredFields()方法返回类的所有属性。

(4)获得每个属性对应的getXXX()和setXXX()然后执行这些方法,把原来的属性拷贝到新的对象中。

三、用反射机制调用对象的方法

package reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InvokeTester {
  public int add(int param1,int param2){
      return param1+param2;
  }
  
  public String echo(String msg){
      return "echo:"+msg;
  }
  
  public static void main(String[] args) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException{
      Class<?> classType=InvokeTester.class;
      Object invokeTester =classType.newInstance();
      
      //获取InvokeTester类的add()方法
      Method addMethod=classType.getMethod("add", int.class,int.class);
      //调用invokeTester对象上的add()方法
      Object result=addMethod.invoke(invokeTester,100,200);
      System.out.println((Integer)result);
      
      //获取InvokeTester类的echo方法
      Method echoMethod=classType.getMethod("echo", java.lang.String.class);
      
    Object echoResult=echoMethod.invoke(invokeTester, "HelloWorld");
    System.out.println(echoResult);
      
  }
}

四、动态创建和访问数组

创建简单的一维数组

public class ArrayTester2 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        
      //创建一个int类型的3维数组,维度分别是5,10,15
      Object array=Array.newInstance(int.class, 5,10,15);
      Object arrayObj=Array.get(array, 3);
      Class<?> cls=arrayObj.getClass().getComponentType();
      System.out.println(array.getClass().getComponentType());
      System.out.println(cls);
      
      arrayObj=Array.get(arrayObj, 5);
      Array.setInt(arrayObj, 10, 37);
      int[][][] arrarCast=(int[][][]) array;
      System.out.println(arrarCast[3][5][10]);
    }
}

 

转载于:https://my.oschina.net/u/2439286/blog/787121

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值