The following example runs MyClass#myMethod()
only if it is public. It does not run it if it is private.
How to run even if private?
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();
}
}
}
}
You have to call setAccessible(true)
on your method.
See the Javadoc of AccessibleObject , which in turn is a supertype of Method.
In your example:
methods.get(i).setAccessible(true);
methods.get(i).invoke(myObject);
EDIT: As GhostCat pointed out in his answer, not all reflection calls return private methods, too. It seems that MethodUtils#getMethodsListWithAnnotation in fact does not return them.
To solve this problem, you'd have to fetch those methods by yourself:
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 ();
}
}
Basically, you need to run a private method from the class itself. Maybe you should rethink your code ? Otherwise, Alex's answer will do the trick.
More informations on access levels : https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
And if you want to use Reflection, you can find even more infos about the behavior here : Java reflection - impact of setAccessible(true)
Actually, there can be two reasons why your code doesn't work:
getMethodsListWithAnnotation
returns a list that simply doesn't include any private methods? ( you see, the mechanism in java reflection to get a hold on private methods is different than for public methods. thus it wouldnt surprise me if that util class is making the same distinction). And in any case: private methods are private for a reason. They represent internal implementation details. They are subject to be changed all the time .
In that sense: your real problem is that you think there is a valid reason to invoke a private method using reflection. You should work on that first . If you really think that method should be annotated; and be called via reflection; then at least make it public .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.