Overview
The last post about reactive programming introduced an experimental library which, among other things, implements method references (aka function pointers) for Java.
If Java allowed for such a syntax, I could imagine a succinct example:
class TestClass{ int add(int a, int b){ return a + b; } public void test(){ FunctionPointer fp = TestClass.add; // <--- Not possible in Java System.out.println((Integer)fp(1,2)); } }
But Java doesn’t allow this syntax, and if we want function pointers, we need to be creative.
A first approach: the reflection API
There is probably more than one definition of a function pointer. In a way, Java’s java.lang.reflect.Method comes pretty close; it is a reference to a method which belongs to a class. When invoking the method, we need to supply an instance of the class and any method arguments. Rephrasing the previous example:
Method m = TestClass.class.getMethod("add", new Class{}{Integer.class, Integer.class}); System.out.println(m.invoke(this, 1,2))
Note that by using the reflection API, we get a reference to a class’ method – we still can (and need to) provide the object on which the method is to be invoked and the method arguments. Furthermore, this approach is not very robust: a misspelled method name or a refactoring gone wrong, changes in the method declaration or method overloading may get us the wrong method picked, or none at all. Ideally we’d like to grab a function pointer in a way that ties it to the type checking system in order to align with refactoring and avoid method argument collusion.
Cooperative methods
Let’s build on the first approach but try to automate a few things. For example, can the code “guess” which method we want the reference to? Probably, if there is only ever one such method in a scope or if we annotate them. But the first solution is rather inflexible and the second won’t survive refactorings.
If the method itself told us its name and arguments, we might get a step closer. As a matter of fact, the Thread.getStackTrace() method will return the name of the current method, so going back to the first example:
int add(int a, int b){ Thread.currentThread().getStackTrace() // <-- Somewhere in here is the method name "add" return a + b; }
How is that helping? Well, it is helping a little because if we could run the method in two different modes, e.g. “recording” mode and “execution” mode, it could, depending on the mode, either return its name or perform the addition. With plenty of artistic liberty taken, it might look similar to this:
Object add(int a, int b){ if (isInRecordingMode()) return getNameFromStackTrace(Thread.currentThread().getStackTrace()); else return a + b; }
Resources
[1] Reactive programming for Java, revisited
https://blog.georgovassilis.com/2014/11/reactive-programming-for-java-revisited.html
[2] reactive-programming github repository
https://github.com/ggeorgovassilis/reactive-programming