Java反射
什么是反射?
反射就是Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息。
获取类
有三个方法,可以获取一个class的Class实例。
- 直接通过
class的静态变量class获取: - 通过一个实例变量提供的方法
getClass()获取 - 知道一个
class的完整类名,可以通过静态方法Class.forName()获取
1 | public class Main { |

获取字段
通过class实例获取字段,java中有如下方法
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field[] getFields():获取所有public的field(包括父类)
- Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
1 | public class Main { |

getField()方法可以获取类的publice方法修饰的成员变量,即使是父类也可以获取,而其余的修饰符则需要使用getDeclaredField()方法获取,该方法可以获取一个类的所有成员变量,但是不能获取到父类的。
获取字段值
要获取字段的值,可以先获取Class实例,再获取Field实例,然后,用Field.get(Object)获取指定实例的指定字段的值。
1 | import java.lang.reflect.Field; |

但是这里我们获取的字段值的修饰符是Public,那如果是Private或者Protected修饰的呢,Protected修饰的话,仍然可以这样获取道,但如果是Private修饰的话需要在调用Object value = f.get(p);前面加上
1 | a.setAccessible(true); |
修改字段值
修改字段值使用的是Field.set(Object, Object)实现的,其中第一个Object参数是指定的实例,第二个Object参数是待修改的值。
1 | import java.lang.reflect.Field; |
获取方法
我们也可以通过Class实例获取所有Method信息
和获取字段差不多
Method getMethod(name, Class...):获取某个public的Method(包括父类)Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)Method[] getMethods():获取所有public的Method(包括父类)Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
获取到了Method对象之后一个,就可以进行下一步操作
Method对象包含一个方法的所有信息:
getName():返回方法名称,例如:"getScore";getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。public是1,private是2,protected是4。
1 | import java.lang.reflect.Method; |

调用方法
调用方法需要先获取方法,然后调用invoke,调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错。
以上面那个例子
1 | import java.lang.reflect.Method; |
和Field类似,对于非public方法,我们虽然可以通过Class.getDeclaredMethod()获取该方法实例,但直接对其调用将得到一个IllegalAccessException。为了调用非public方法,我们通过Method.setAccessible(true)允许其调用。
调用构造方法
如果通过反射来创建新的实例,可以调用Class提供的newInstance()方法:
1 | Person p = Person.class.newInstance(); |
调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法,如果要调用有参构造方法,或者构造函数是非Public的就需要使用下面的这些。
通过Class实例获取Constructor的方法如下:
getConstructor(Class...):获取某个public的Constructor;getDeclaredConstructor(Class...):获取某个Constructor;getConstructors():获取所有public的Constructor;getDeclaredConstructors():获取所有Constructor。
Constructor总是当前类定义的构造方法,和父类无关,因此不存在多态的问题。
调用非public的Constructor时,必须首先通过setAccessible(true)设置允许访问。setAccessible(true)可能会失败。
参考自:https://www.liaoxuefeng.com/wiki/1252599548343744/1255945147512512