以下示例仅在MyClass#myMethod()
是公共的情况下运行。如果它是私有的,它不会运行它。
如何运行即使是私有的?
import org.apache.commons.lang3.reflect.MethodUtils;
import javax.annotation.PostConstruct;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Created by dims on 13.10.2016.
*/
public class CallPrivateMethodTest {
@Retention(RUNTIME)
@Target(METHOD)
public @interface MyAnnotation {
}
public static class MyClass {
@MyAnnotation
private void myMethod() {
System.out.println("myMethod() ran");
}
}
public static void main(String[] args) {
MyClass myObject = new MyClass();
List<Method> methods = MethodUtils.getMethodsListWithAnnotation(myObject.getClass(), MyAnnotation.class);
for(int i=0; i<methods.size(); ++i) {
try {
methods.get(i).invoke(myObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
你必须在你的方法中调用setAccessible(true)
。
参见AccessibleObject的Javadoc,它又是Method的超类型。
在你的例子中:
methods.get(i).setAccessible(true);
methods.get(i).invoke(myObject);
EDIT:正如GhostCat在他的回答中指出的,并不是所有的反射调用都返回私有方法。似乎MethodUtils#getMethodsListWithAnnotation实际上并没有返回它们。
要解决这个问题,你必须自己获取这些方法:
MyClass myObject = new MyClass ();
Method[] allMethods = myObject.getClass ().getDeclaredMethods ();
List<Method> annotatedMethods = Arrays.stream (allMethods)
.filter (m -> m.getAnnotation (MyAnnotation.class) != null)
.collect (Collectors.toList ());
for (Method method: annotatedMethods) {
try {
method.setAccessible (true);
method.invoke (myObject);
} catch (IllegalAccessException e) {
e.printStackTrace ();
} catch (InvocationTargetException e) {
e.printStackTrace ();
}
}
基本上,需要从类本身运行一个私有方法。也许你应该重新考虑你的代码?否则,Alex的答案就会起作用。
访问级别的更多信息:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
如果你想使用反射,你可以在这里找到更多关于行为的信息:Java反射- setAccessible(true)的影响
实际上,您的代码不能工作可能有两个原因:
- 那个私有方法出现在那个列表中;但是在调用它之前,你必须使它可访问(你已经得到了答案)
- 取决于你正在使用的Util类的实现,也许
getMethodsListWithAnnotation
返回一个列表,根本不包括任何私有方法?(您可以看到,Java反射中获取私有方法的机制与获取公共方法的机制不同。因此,如果util类做出同样的区分,我不会感到惊讶)。