java学习笔记 -- 反射

October . 22 . 2018

一、反射机制

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

以上是比较官方的解释, 简而言之就是通过 jvm 编译产生的 .class 文件来反映出对应的类(.java)文件罢了.

反射的基本步骤

  • 获得Class对象
  • 获得类的属性, 方法或构造函数
  • 创建对象, 访问属性,以及调用方法


举个栗子:

// 获得Class对象 
Class cls = Class.forName("my.Student");
// 取得对象的所有方法及成员变量
Method[] methods = cls.getMethods();
Field[] fields = cls.getFields(); 
// 创建对象
Object obj = cls.newInstance();

通过这三步就可以基本实现一个通过 class 反射对象的一个过程. 乍一看可能有点懵逼, 这有什么用, 难道老老实实的 new 一个对象不好吗, 当然在可以直接new对象的情况下, 肯定要选择简单明了的方法, 但是在某些特定情况下直接创建对象会变得很不现实, 比如:

  1. 如果我只知道一个类的名称/或者它的一个实例对象, 我就能把这个类的所有方法和变量的信息找出来(方法名,变量名,方法,修饰符,类型,方法参数等等所有信息)。
  2. 如果我还明确知道这个类里某个变量的名称,我还能得到这个变量当前的值。
  3. 当然,如果我明确知道这个类里的某个方法名+参数个数类型,我还能通过传递参数来运行那个类里的那个方法。

再举个完整的栗子:

package my;
// 学生类
public class Student {
    private int id;
    private String name;
    private String phone;
    public Student() {
    }
    public Student(int id, String name, String phone)
    {
        this.id = id;
        this.name = name;
        this.phone = phone;
    }
    @Override
    public boolean equals(Object obj) {
        if (this.getClass().isInstance(obj)) {
            return this.id == ((Student) obj).id;
        } else if(String.class.isInstance(obj)) {
            return this.name.equals((String)obj);
        } else if(Integer.class.isInstance(obj)) {
            return this.id == (Integer)obj;
        }
        return false;
    }
    @Override
    public String toString() {
        return "(" + id + "," + name + "," + phone + ")";
    }
    public int getId()
    {
        return id;
    }
    public void setId(int id)
    {
        this.id = id;
    }
}



测试类

package my;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Hello {

    public static void isStudentByObject(Object obj)
    {
        Class cls = Student.class;
        if (cls.isInstance(obj))
        {
            System.out.println("是学生类的实例..");
        }
    }

    public static void isStudentByName(Object obj)
    {
        String clsName = obj.getClass().getName();
        if (clsName.equals("my.Student")) {
            System.out.println("是学生类的实例");
        }
    }

    public static Method[] getMethodList() throws ClassNotFoundException {
        Class cls = Class.forName("my.Student");
        Method[] methods = cls.getMethods();
        Field[] fields = cls.getFields();
        return methods;
    }

    public static void getMethod(Class clas) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        String methodName = "setId";

        // 创建实例
        Object obj = clas.newInstance();

        // 方法参数类型列表
        Class[] parameterTypes = { int.class };
        Method m = clas.getMethod(methodName, parameterTypes);

        // 方法参数列表
        Object[] paramsForMethod = { 123 };

        // 调用方法
        m.invoke(obj, paramsForMethod);

        // 打印
        System.out.println((Student)obj);
        System.out.println("ok!");
    }

 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class cls = Class.forName("my.Student");
        getMethod(cls);
    }

}

代码运行结果如下:

reflectTest.PNG

done!