Java反射机制概念

Java的反射机制本质是在运行时,通过对象实例来动态加载对象的信息。是为了解决在运行期间,对某个实例不知道是什么类的情况下,如何调用其声明方法、字段的问题。

场景举例

现有主类Main、Person类和Person的子类Student,主类的main函数中获取Student类的一个实例stu,并传入test方法。但是由于test方法的参数是顶级父类Object对象,调用test方法时可以传入任何对象,所以对于test方法内部来说,并不能知道实际传入的对象是什么,如果想要在test中访问具体传入对象的属性和方法怎么办呢?

这种情况下,通过反射就可以在test方法中得到此时传入的object具体实例以及访问它的方法和字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Main{
public static void main(String[] args){
Student stu = new Student();
stu.age =22;
test(stu);
}

public static void test(Object object){

}
}

class Student extends Person{
public int score;
void hello(){
System.out.println("hello");
}
}

class Person{
public int age;
}

获取class实例的方式

  • 当知道class时(以java.lang.String为例),直接通过class的静态变量class获取
1
Class c = String.class;
  • 当知道class完整类名时(以java.lang.String为例),通过静态方法Class.forName()获取
1
Class c = Class.forName("java.lang.String");
  • 当有实例变量时,可以通过改实例变量的getClass()方法获取,如上例子中test方法就可通过这种方式获得object的真正class实例
1
2
3
public static void test(Object object){  
Class c = object.getClass();
}

获取字段和方法的方式

对于任意一个Object实例,只要获取了其class,就可以获取关于它的全部数据结构

字段(field)

  • 获取字段信息

    • Field getField(name)获取某个publicfield(包括从父类继承的)
    1
    2
    3
    4
    5
    //以上文test方法为例
    public static void test(Object object){
    Class c = object.getClass();
    Field ageField = c.getField("age") //ageField值为:public int Person.age
    }
    • Field[] getFields()获取所有publicfield(包括从父类继承的)
    • Field getDeclaredField(name):获取当前类的某个field(不包括父类)
    • Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
  • 获取字段值

    • 通过get方法获得具体值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //以上文test方法为例
    import java.lang.reflect.Field;
    ...
    public static void test(Object object){
    Class c = object.getClass();
    Field ageField = c.getField("age");
    //已知age是int型,通过ageField.getInt,传入object,获得具体值
    System.out.println(ageField.getInt(object));//输出22
    }
    ...

方法

  • 获取方法信息

    • Method getMethod(name, Class...):获取某个publicMethod(包括从父类继承的)
    • Method[] getMethods():获取所有publicMethod(包括从父类继承的)
    • Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
    • Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
  • 调用方法

    • 通过invoke方法进行调用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //以上文test方法为例
    import java.lang.reflect.Method;
    ...
    public static void test(Object object){
    Class c = object.getClass();
    Method m = c.getDeclaredMethod('hello');
    //传入object,通过m.invoke调用方法。如果hello方法有参数,通过m.invoke(object,parm1,parm2...)传入参数
    m.invoke(object);
    }
    ...

用途

  • 通过反射机制访问java对象的属性和方法等
  • 开发通用框架,通过反射可以根据配置文件加载不同类或对象,调用不同的方法

参考文章