java 反射demo

基于类的反射
Class 对象为您提供接入类元数据的反射的所有基本hook。这类元数据包括关于类自身的信息,如包和类的父类,以及该类实施的接口。它还包括该类定义的构造函数、字段和方法的详细信息。
这些最后的项目都是编程中最经常使用的项目, 因此我将在本小节的稍后部分给出一些与它们协作的实例。 对于以下三类组件中的任何一类来说
-- 构造函数、字段和方法 -- java.lang.Class 提供四种独立的反射调用,以不同的方式来获得信息。调用都遵循一种标准格式。以下是用于查找构造函数的一组反射调用: Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数, Constructor[] getConstructors() -- 获得类的所有公共构造函数 Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关) Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关) 每类这些调用都返回一个或多个 java.lang.reflect.Constructor 函数。这种 Constructor 类定义 newInstance 方法,
它采用一组对象作为其唯一的参数,然后返回新创建的原始类实例。该组对象是用于构造函数调用的参数值。
作为解释这一工作流程的实例,假设您有一个 TwoString 类和一个使用一对 String s的构造函数,如清单1所示: 清单1:从一对字符串创建的类
&#160 1 2 3 4 5 6 7 public class TwoString { private String m_s1, m_s2; public TwoString(String s1, String s2) { m_s1 = s1; m_s2 = s2; } } 清单2中的代码获得构造函数并使用它来创建使用 String s "a" 和 "b" 的 TwoString 类的一个实例: 清单2:构造函数的反射调用 1 2 3 4 Class[] types = new Class[] { String.class, String.class }; Constructor cons = TwoString.class.getConstructor(types); Object[] args = new Object[] { "a", "b" }; TwoString ts = cons.newInstance(args);


通过反射增加字段
获得字段信息的 Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:
Field getField(String name) -- 获得命名的公共字段
Field[] getFields() -- 获得类的所有公共字段
Field getDeclaredField(String name) -- 获得类声明的命名的字段
Field[] getDeclaredFields() -- 获得类声明的所有字段
尽管与构造函数调用类似,在字段方面仍存在一个重要的区别:前两个变量返回可以通过类接入的公共字段的信息 -- 即使它们来自于祖先类。后两个变量返回类直接声明的字段的信息 -- 与字段的接入类型无关。
调用返回的 java.lang.reflect.Field 实例定义所有主类型的 getXXX 和 setXXX 方法,以及与对象引用协作的通用 get 和 set 方法。
您可以根据实际的字段类型自行选择一种适当的方法,而 getXXX 方法将自动处理扩展转换(如使用 getInt 方法来检索一个字节值)。
public class employee {
private int id;
private String name;
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public employee() {
    super();
    // TODO Auto-generated constructor stub
}
public employee(int id, String name) {
    super();
    this.id = id;
    this.name = name;
}

}
import java.lang.reflect.Field;
public class app {
    
    public int incrementField(String name, Object obj) throws Exception {
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);                                      //打开private访问权限   并修改该字段的值
        int value = field.getInt(obj) + 1;
        field.setInt(obj, value);
        return value;
    }    
    
public static void main(String[] args) throws Exception {
    app a1= new app();
    int x=a1.incrementField("id", new employee(10,"xiaoming"));
    System.out.println(x);
}
}
例如,如果对象为一个整数 count 值定义了 getCount 和 setCount 方法,您可以在一次调用中向该方法传递“count”作为 name 参数,以增加该值。
清单4:通过反射增加一个JavaBean 属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public int incrementProperty(String name, Object obj) {
    String prop = Character.toUpperCase(name.charAt(0)) +
        name.substring(1);
    String mname = "get" + prop;
    Class[] types = new Class[] {};
    Method method = obj.getClass().getMethod(mname, types);
    Object result = method.invoke(obj, new Object[0]);
    int value = ((Integer)result).intValue() + 1;
    mname = "set" + prop;
    types = new Class[] { int.class };
    method = obj.getClass().getMethod(mname, types);
    method.invoke(obj, new Object[] { new Integer(value) });
    return value;
}
为了遵循JavaBeans惯例,我把属性名的首字母改为大写,然后预先考虑 get 来创建读方法名, set 来创建写方法名。JavaBeans读方法仅返回值,而写方法使用值作为唯一的参数,
因此我规定方法的参数类型以进行匹配。最后,该惯例要求方法为公共,因此我使用查找格式,查找类上可调用的公共方法。 这一实例是第一个我使用反射传递主值的实例,因此现在我们来看看它是如何工作的。
基本原理很简单:无论什么时候您需要传递主值,只需用相应封装类的一个实例(在 java.lang 包中定义)来替换该类主值。这可以应用于调用和返回。
、因此,当我在实例中调用 get 方法时,我预计结果为实际
int 属性值的 java.lang.Integer 封装。
反射数组
数组是Java编程语言中的对象。与所有对象一样,它们都有类。如果您有一个数组,使用标准 getClass 方法,您可以获得该数组的类,就象任何其它对象一样。
但是, 不通过现有的实例来获得类不同于其它类型的对象。即使您有一个数组类,您也不能直接对它进行太多的操作
-- 反射为标准类提供的构造函数接入不能用于数组,
而且数组没有任何可接入的字段,只有基本的 java.lang.Object 方法定义用于数组对象。 数组的特殊处理使用 java.lang.reflect.Array 类提供的静态方法的集合。该类中的方法使您能够创建新数组,获得数组对象的长度,读和写数组对象的索引值。 清单5显示了一种重新调整现有数组大小的有效方法。它使用反射来创建相同类型的新数组,然后在返回新数组之前,在老数组中复制所有数据。 清单
5:通过反射来扩展一个数组 1 2 3 4 5 6 7 public Object growArray(Object array, int size) { Class type = array.getClass().getComponentType(); Object grown = Array.newInstance(type, size); System.arraycopy(array, 0, grown, 0, Math.min(Array.getLength(array), size)); return grown; }
清单 8:方法接入性能测试代码

public int callDirectArgs(int loops) {
    int value = 0;
    for (int index = 0; index < loops; index++) {
        value = step(value);
    }
    return value;                        //使用直接变量 进行运算  ,直接求值并返回值       
}
public int callReferenceArgs(int loops) {
    TimingClass timing = new TimingClass();
    int value = 0;
    for (int index = 0; index < loops; index++) {
        value = timing.step(value);
    }
    return value;                              //使用 类的字段 进行运算 ,求值并返回值     
}
public int callReflectArgs(int loops) throws Exception {
    TimingClass timing = new TimingClass();
    try {
        Method method = TimingClass.class.getMethod
            ("step", new Class [] { int.class });
        Object[] args = new Object[1];
        Object value = new Integer(0);
        for (int index = 0; index < loops; index++) {              //使用反射字段  进行运算 ,求值并返回值。
            args[0] = value;
            value = method.invoke(timing, args);
        }
        return ((Integer)value).intValue(); 
    } catch (Exception ex) {
        System.out.println("Error using reflection");
        throw ex;
    }
}
原文地址:https://www.cnblogs.com/yimian/p/7954546.html