Java中的反射

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

例如有如下Person

class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name) {
        System.out.println(name);
    }

    public Person(String name, int age) {
        System.out.println(name + " " + age);
    }

    private void getName() {
        System.out.println("Person.getName " + this.name);
    }
}

获得 Class 类

第一种方式是通过Object类的getClass()方法;

Person person = new Person();
Class personClass = person.getClass();

第二种为Person.class,第三种方式为Class.forName("com.mycompany.app.Person")

这样看起来第三种方式更好,只需要传入字符串即可,但是需要带上包名。

获得构造方法

public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的)
返回多个构造方法

public Constructor<?>[] getConstructors() 获取所有的 public 修饰的构造方法

public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法(包含私有的)

获取构造方法示例

public static void main(String[] args) {
    Class personClass = null;
    try {
        personClass = Class.forName("com.mycompany.app.Person");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    Constructor<Person>[] personConstructors = personClass.getDeclaredConstructors();
    for (Constructor personConstructor : personConstructors) {
        System.out.println(personConstructor);
    }
}

输出

public com.mycompany.app.Person()
public com.mycompany.app.Person(java.lang.String)
public com.mycompany.app.Person(java.lang.String,int)

获取变量与方法

返回一个成员变量

public Field getField(String name) 获取指定的 public 修饰的变量

public Field getDeclaredField(String name) 获取指定的任意变量(包含私有)

返回多个成员变量

public Field[] getFields() 获取所有 public 修饰的变量

public Field[] getDeclaredFields() 获取所有的变量 (包含私有)

返回获取一个方法:

public Method getMethod(String name, Class<?>... parameterTypes) 获取public修饰的方法

public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取任意的方法,包含私有的

参数 1: name 要查找的方法名称; 参数 2: parameterTypes 该方法的参数类型

返回获取多个方法:

public Method[] getMethods() 获取本类与父类中所有public修饰的方法

public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)

如下示例,使用反射给变量赋值并且调用特定方法。

public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    Class personClass = Class.forName("com.mycompany.app.Person");
    Constructor<Person> personConstructor = personClass.getConstructor(String.class);
    Field nameField = personClass.getDeclaredField("name");
    Person person = personConstructor.newInstance("Jason");
    nameField.setAccessible(true);
    nameField.set(person, "leevare");
    Method method = personClass.getDeclaredMethod("getName");
    method.setAccessible(true);
    method.invoke(person, null);
    System.out.println(person);
}

输出

Jason
Person.getName leevare
com.mycompany.app.Person@38082d64

这里将nameFiledmethod通过setAccessible设置值为true,可以取消 Java 语言访问检查,否则调用或者给private的内容赋值会报错。方法可以通过invoke来进行调用,第一个参数为实例对象,之后为方法的参数。

使用反射还可以跳过泛型的约束,例如如下示例

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    ArrayList<String> list = new ArrayList<>();
    list.add("word");
    Class listClass = Class.forName("java.util.ArrayList");
    Method method = listClass.getMethod("add", Object.class);
    method.invoke(list, 132);
    System.out.println(list);
}

本来list只可以添加String类型的值,但是使用反射之后,可以向其中添加任意类型的值,上述输出结果为[word, 132]

本文整理自:http://www.cnblogs.com/ginb/p/7118078.html

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注