我是靠谱客的博主 敏感花瓣,最近开发中收集的这篇文章主要介绍java反射调用方法_Java Method.invoke()反射调用一个方法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

首页 > 基础教程 > 反射 > 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()反射调用一个方法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部