Problem
One friend suggested an interesting problem. Given the following code:
public class OuterClass {
private String message = "Hello World";
private class InnerClass {
private String getMessage() {
return message;
}
}
}
From an external class, how may I print the message
variable content? Of course, changing the accessibility of methods or fields is not allowed.
(the source here, but it is a french blog)
Solution
The code to solve this problem is the following:
try {
Method m = OuterClass.class.getDeclaredMethod("access$000", OuterClass.class);
OuterClass outerClass = new OuterClass();
System.out.println(m.invoke(outerClass, outerClass));
} catch (Exception e) {
e.printStackTrace();
}
Note that the access$000
method name is not really standard (even if this format is the one that is strongly recommanded), and some JVM will name this method access$0
. Thus, a better solution is to check for synthetic methods:
Method method = null;
int i = 0;
while ((method == null) && (i < OuterClass.class.getDeclaredMethods().length)) {
if (OuterClass.class.getDeclaredMethods()[i].isSynthetic()) {
method = OuterClass.class.getDeclaredMethods()[i];
}
i++;
}
if (method != null) {
try {
System.out.println(method.invoke(null, new OuterClass()));
} catch (Exception e) {
e.printStackTrace();
}
}
So the interesting point in this problem is to highlight the use of synthetic methods. With these methods, I can access a private field as it was done in the solution. Of course, I need to use reflection, and I think that the use of this kind of thing can be quite dangerous...
Question
What is the interest - for me, as a developer - of a synthetic method? What can be a good situation where using the synthetic can be useful?
As you demonstrate, Java access modifiers are merely informative, and they can be circumvented by using reflection. So your questions is roughly equivalent to "what is the interest of circumventing an access modifier?" Apart from malicious purposes, debugging comes to mind; you could for instance log the internal state of some library's internals from outside the library, without having to touch the library code itself at all. Another example is co-operation with scripting languages; if you don't know on compile-time which classes and methods are available, reflection can be quite useful. For instance, Jython's internals uses huge amounts of reflection all around.