- 反射机制的概要
- 通过反射创建类
- 获取Class的方式
- 通过Class实例化对象
- 通过反射调用类方法
- 通过Class获取类中的方法
- 通过Method调用方法
- 通过反射修改类属性
- 通过Class获取属性
- 通过Class修改对象属性
JAVA的反射机制,就是可以通过全类名,获取当前类、调用当前类方法,以及获取或修改当前类属性的一个机制。
总结来说:就是通过类对象来获取类信息的一个途径。
如示例:若A类无法引用B类的话,但是又要调用B类的方法,其实就可以调用反射获取B类并且执行B类的方法。
通过反射创建类
首先认识类对象 :Class,类对象中中记录了这个类包含了哪些属性、哪些方法、以及有哪些构造方法等信息。
对于Class的话在这里不多做介绍,具体可以看这个博客:类对象详细介绍.
// A的全类名为: package.pojo.A
// 首先有以下几种方式获取类对象
Class a = Class.forName("package.pojo.A"); //参数为类的全类名
Class b = A.class;
Class c = new A().getClass();
获取了 Class 类对象之后,就可以通过类对象去调用方法、获取数据等。
通过Class实例化对象// 通过Class类对象去实例化对象
try {
// 这里用一种方式去获取Class,也可以用其他方式
Class a = Class.forName("package.pojo.A");
// 通过类对象获取默认构造器
Constructor c = a.getConstructor();
// 通过构造器调用构造方法完成实例化
A a1 = (A)c.newInstance();
// 此时已经获取到A对象,可以通过A对象做后续的事情了
} catch (Exception e) {
e.printStackTrace();
}
通过反射调用类方法
通过Class去调用类的方法的话,应该是我日常中使用反射用的最多的一个方式了,很多时候无法引入类我都会使用反射去调用所需要的类的方法
通过Class获取类中的方法我们可以通过 getMethod() 获取到Method对象,来调用类方法
当然还有 getDeclaredMethod() 这两个区别请看下面获取属性的方法即可
// 首先请看Class.getMethod()的源码
private Method getMethod0(String name, Class>[] parameterTypes, boolean includeStaticMethods) {
// 父接口的方法数组
MethodArray interfaceCandidates = new MethodArray(2);
// 获取方法的Method对象
Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
// 如果不为空,说明从本类或者父类中获取到了root对象的拷贝对象,直接返回
if (res != null)
return res;
// Not found on class or superclass directly
interfaceCandidates.removeLessSpecifics();
// 如果没从本类/父类中获取到方法,则从父接口中获取方法
return interfaceCandidates.getFirst(); // may be null
}
看完源码之后,其实获取Method对象的就很清晰明了的了,下面是示例
// 首先存在方法为
public String isBigData(String name, Integer number) {
// 省略方法体
}
// 首先肯定要获取相对应的Class对象
Class a = Class.forName("package.pojo.A");
// 通过调用Class.getMethod()获取方法
// 第一个参数为方法名
// 第二个参数为方法所需参数的Class,因为目前是两个参数,所以要传递一个数组如果方法只有一个参数则传递一个参数即可
// 第三个参数,由于当前方法不是Static,不需要传递
Method isBigDataMethod = a.getMethod("isBigData", new Class[] { String.class, int.class });
通过Method调用方法
上面已经学习过了如何通过Class获取Method方法对象,此时就可以通过此方法对象去执行方法了
调用方法主要是用到 Method.invoke() 即可
// Method.invoke()源码如下
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
调用方式如下
// 省略之前步骤,获取Method对象
Method isBigDataMethod = a.getMethod("isBigData", new Class[] { String.class, int.class });
// 由于调用A对象中的方法需要有A对象,所以先创建出来
Class a = Class.forName("package.pojo.A");
Constructor c = a.getConstructor();
Objcet a1 = c.newInstance();
// 直接调用Method.invoke()即可
// 第一个参数调用方法的对象
// 第2,3..个参数,就是调用方法所需的对象
String rtn = isBigDataMethod.invoke(a1, "value1", 3);
// 此时就直接完成了方法的调用了
通过反射修改类属性 通过Class获取属性
Class中存在两个方法可以获取类属性,分别为
Field[] getFields() / Field getField(String name)
Field[] getDeclaredFields() / Field getDeclaredField(String name)
getFields(),只能获取public的属性,无法获取其他属性,Class源码和解释如下
// 通过Member.PUBLIC参数来控制只获取public属性
@CallerSensitive
public Field[] getFields() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyFields(privateGetPublicFields(null));
}
getDeclaredFields(),则能获取public属性以及private属性,但是不能获取继承的属性
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyFields(privateGetDeclaredFields(false));
}
则我们可以通过两种方式来获取属性
通过Class修改对象属性既然都可以将属性获取出来了,此时也可以通过反射对对象设置属性值
// 首先通过反射来获取Class类
Class a = Class.forName("packeage.pojo.A");
// 通过Class实例化一个类
A a = (A) a.getConstructor().newInstance();
// 获取所有属性
Fields fields = a.getFields();
// 可以通过属性名称来获取Field对象
Field attrA = a.getField("属性名称");
// 直接调用Field.set(类对象Object, value)即可修改属性值
attrA.set(a, "value"); // 此时就是给a对象的attrA属性设置值了



