概述
首页 > 基础教程 > 反射 > Reflection API
Java Method.invoke()反射调用一个方法
java.lang.reflect.Method.invoke() 方法来反射调用一个方法,当然一般只用于正常情况下无法直接访问的方法(比如:private 的方法,或者无法或者该类的对象)。
定义
public native Object invoke(Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
参数:
第一个参数是方法属于的对象(如果是静态方法,则可以直接传 null)
第二个可变参数是该方法的参数
返回值:
Object
异常:
如果调用的方法有抛出异常,异常会被 java.lang.reflect.InvocationTargetException 包一层
源码分析
public final class Method extends AccessibleObject implements GenericDeclaration, Member {
// ...
private volatile MethodAccessor methodAccessor;
// For sharing of MethodAccessors. This branching structure is
// currently only two levels deep (i.e., one root Method and
// potentially many Method objects pointing to it.)
private Method root;
// ...
public Object invoke(Object obj, Object... args)throws IllegalAccessException, IllegalArgumentException,InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class caller = Reflection.getCallerClass(1);
Class targetClass = ((obj == null || !Modifier.isProtected(modifiers))
? clazz
: obj.getClass());
boolean cached;
synchronized (this) {
cached = (securityCheckCache == caller)
&& (securityCheckTargetClassCache == targetClass);
}
if (!cached) {
Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
synchronized (this) {
securityCheckCache = caller;
securityCheckTargetClassCache = targetClass;
}
}
}
}
if (methodAccessor == null) acquireMethodAccessor();
return methodAccessor.invoke(obj, args);
}
// NOTE that there is no synchronization used here. It is correct
// (though not efficient) to generate more than one MethodAccessor
// for a given Method. However, avoiding synchronization will
// probably make the implementation more scalable.
private void acquireMethodAccessor() {
// First check to see if one has been created yet, and take it
// if so
MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor();
if (tmp != null) {
methodAccessor = tmp;
return;
}
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
}
// ...
}
Method.invoke()实际上并不是自己实现的反射调用逻辑,而是委托给sun.reflect.MethodAccessor来处理。 每个实际的Java方法只有一个对应的Method对象作为root,。这个root是不会暴露给用户的,而是每次在通过反射获取Method对象时新创建Method对象把root包装起来再给用户。在第一次调用一个实际Java方法对应得Method对象的invoke()方法之前,实现调用逻辑的MethodAccessor对象还没创建;等第一次调用时才新创建MethodAccessor并更新给root,然后调用MethodAccessor.invoke()真正完成反射调用。
例子
public class MethodInvoke extends BaseTestClass {
private boolean checkString(String s) {
printFormat("checkString: %sn", s);
return TextUtils.isEmpty(s);
}
private static void saySomething(String something) {
System.out.println(something);
}
private String onEvent(TestEvent event) {
System.out.format("Event name: %sn", event.getEventName());
return event.getResult();
}
static class TestEvent {
private String eventName;
private String result;
public TestEvent(String eventName, String result) {
this.eventName = eventName;
this.result = result;
}
public String getResult() {
return result;
}
public String getEventName() {
return eventName;
}
}
public static void main(String[] args) {
try {
Class < ?>cls = Class.forName("net.sxkeji.shixinandroiddemo2.test.reflection.MethodInvoke");
MethodInvoke object = (MethodInvoke) cls.newInstance();
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method declaredMethod: declaredMethods) {
String methodName = declaredMethod.getName(); //获取方法名
Type returnType = declaredMethod.getGenericReturnType(); //获取带泛型的返回值类型
int modifiers = declaredMethod.getModifiers(); //获取方法修饰符
// declaredMethod.setAccessible(true);
if (methodName.equals("onEvent")) {
TestEvent testEvent = new TestEvent("shixin's Event", "cuteType");
try {
Object invokeResult = declaredMethod.invoke(object, testEvent);
System.out.format("Invoke of %s, return %s n", methodName, invokeResult.toString());
} catch(InvocationTargetException e) { //处理被调用方法可能抛出的异常
Throwable cause = e.getCause();
System.out.format("Invocation of %s failed: %sn", methodName, cause.getMessage());
}
} else if (returnType == boolean.class) {
try {
declaredMethod.invoke(object, "shixin's parameter");
} catch(InvocationTargetException e) {
Throwable cause = e.getCause();
System.out.format("Invocation of %s failed: %sn", methodName, cause.getMessage());
}
} else if (Modifier.isStatic(modifiers) && !methodName.equals("main")) { //静态方法,调用时 object 直接传入 null
try {
declaredMethod.invoke(null, "static method");
} catch(InvocationTargetException e) {
Throwable cause = e.getCause();
System.out.format("Invocation of %s failed: %sn", methodName, cause.getMessage());
}
}
}
} catch(ClassNotFoundException e) {
e.printStackTrace();
} catch(InstantiationException e) {
e.printStackTrace();
} catch(IllegalAccessException e) {
e.printStackTrace();
}
}
}
执行结果:
checkString: shixin's parameter
Invocation of checkString failed: Stub!
Event name: shixin's Event
Invoke of onEvent, return cuteType
static method
Process finished with exit code 0
总结
1. Method.invoke()本身要用数组包装参数;而且每次调用都必须检查方法的可见性(在Method.invoke()里),也必须检查每个实际参数与形式参数的类型匹配性(在NativeMethodAccessorImpl.invoke0()里或者生成的Java版MethodAccessor.invoke()里)
2. Method.invoke()就像是个独木桥一样,各处的反射调用都要挤过去,在调用点上收集到的类型信息就会很乱,影响内联程序的判断,使得Method.invoke()自身难以被内联到调用方。
版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。
最后
以上就是敏感花瓣为你收集整理的java反射调用方法_Java Method.invoke()反射调用一个方法的全部内容,希望文章能够帮你解决java反射调用方法_Java Method.invoke()反射调用一个方法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复