In Java you can "capture" a "method call on object" as a Runnable, as in belows example.
Later, having access to this instance of Runnable, is it possible to actually access the "captured" object and the method parameters of a method which is called (if possible this probably needs to be done via reflection).
For example:
class SomePrintingClass {
public void print(String myText) {
System.out.println(myText);
}
}
public class HowToAccess {
public static void main(String[] args) throws Exception {
final String myText = "How to access this?";
final SomePrintingClass printer = new SomePrintingClass();
Runnable r = () -> printer.print(myText); // capture as Runnable
inspect(r);
}
private static void inspect(Runnable runnable) {
// I have reference only to runnable... can I access "printer" here
}
}
Is it possible in the "inspect" method to access (probably via reflection) "printer" object and "myText" which was passed as a parameter?
It is possible, because the captured references are translated into fields of the runnable (as with all anonymous classes). The names will be not be consistent however.
I found by testing that you need to make myText
non-final
, otherwise it will be seen as a compile time constant and in-lined (and will not be accessible as a field):
private static void inspect(Runnable runnable) throws Exception {
for(Field f : runnable.getClass().getDeclaredFields()) {
f.setAccessible(true);
System.out.println("name: " + f.getName());
Object o = f.get(runnable);
System.out.println("value: " + o);
System.out.println("class: " + o.getClass());
System.out.println();
}
}
Prints:
name: arg$1
value: test.SomePrintingClass@1fb3ebeb
class: class test.SomePrintingClass
name: arg$2
value: How to access this?
class: class java.lang.String
With reflection, it is not possible to get local variables and method parameter values. Instead you can use AOP to intercept the method call and inspect the parameters.
Check if you want something as the below code where I have passed the runnable to a Thread object in your inspect method.
class SomePrintingClass {
public void print(String myText) {
System.out.println(myText);
}
}
public class HowToAccess {
public static void main(String[] args) throws Exception {
final String myText = "How to access this?";
final SomePrintingClass printer = new SomePrintingClass();
Runnable r = () -> printer.print(myText); // capture as Runnable
inspect(r);
}
private static void inspect(Runnable runnable) {
Thread t = new Thread(runnable);
t.start();
}
}
output will be:
How to access this?