反射机制的概要
?JAVA的反射机制,就是可以通过全类名,获取当前类、调用当前类方法,以及获取或修改当前类属性的一个机制。 ?总结来说:就是通过类对象来获取类信息的一个途径。 ?如示例:若A类无法引用B类的话,但是又要调用B类的方法,其实就可以调用反射获取B类并且执行B类的方法。
通过反射创建类
首先认识类对象 :Class,类对象中中记录了这个类包含了哪些属性、哪些方法、以及有哪些构造方法等信息。 对于Class的话在这里不多做介绍,具体可以看这个博客:类对象详细介绍.
获取Class的方式
Class a = Class.forName("package.pojo.A");
Class b = A.class;
Class c = new A().getClass();
获取了 Class 类对象之后,就可以通过类对象去调用方法、获取数据等。
通过Class实例化对象
try {
Class a = Class.forName("package.pojo.A");
Constructor c = a.getConstructor();
A a1 = (A)c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
通过反射调用类方法
通过Class去调用类的方法的话,应该是我日常中使用反射用的最多的一个方式了,很多时候无法引入类我都会使用反射去调用所需要的类的方法
通过Class获取类中的方法
我们可以通过 getMethod() 获取到Method对象,来调用类方法 当然还有 getDeclaredMethod() 这两个区别请看下面获取属性的方法即可
private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
MethodArray interfaceCandidates = new MethodArray(2);
Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
if (res != null)
return res;
interfaceCandidates.removeLessSpecifics();
return interfaceCandidates.getFirst();
}
看完源码之后,其实获取Method对象的就很清晰明了的了,下面是示例
public String isBigData(String name, Integer number) {
}
Class a = Class.forName("package.pojo.A");
Method isBigDataMethod = a.getMethod("isBigData", new Class[] { String.class, int.class });
通过Method调用方法
上面已经学习过了如何通过Class获取Method方法对象,此时就可以通过此方法对象去执行方法了
调用方法主要是用到 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;
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
调用方式如下
Method isBigDataMethod = a.getMethod("isBigData", new Class[] { String.class, int.class });
Class a = Class.forName("package.pojo.A");
Constructor c = a.getConstructor();
Objcet a1 = c.newInstance();
String rtn = isBigDataMethod.invoke(a1, "value1", 3);
通过反射修改类属性
通过Class获取属性
Class中存在两个方法可以获取类属性,分别为 Field[] getFields() / Field getField(String name) Field[] getDeclaredFields() / Field getDeclaredField(String name)
getFields(),只能获取public的属性,无法获取其他属性,Class源码和解释如下
@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 a = Class.forName("packeage.pojo.A");
A a = (A) a.getConstructor().newInstance();
Fields fields = a.getFields();
Field attrA = a.getField("属性名称");
attrA.set(a, "value");
|