How to use Function Pointers in Java
Java doesn't have a real concept of pointers but luckily we can emulate the behavior with method references.
Table of Contents
Introduction
Pointers are objects that store a memory address and can save memory by directly pointing to a target object, array, or variable address instead of passing by value. Sadly Java doesn't have a "real" concept of pointers. Lucky for us, there's a workaround using method references that comes close to the real thing.
Function Pointers
A function pointer is a pointer that points to the address of a function. Some uses are creating a callback routine by creating a function that calls another function based on its execution or storing an array of function pointers for dynamically calling methods (Ex. Storing CPU instructions for an emulator).
Simulating a Function Pointer
There are four kinds of method references, and we are using the kind that refers to an instance method of a particular object.
Start by defining an interface that defines the method signatures of the method(s) you are pointing to.
1// Wrapping interface 2private interface FunctionPointer { 3 // Method signatures of pointed method 4 void methodSignature(int a); 5}
Next, create methods with the target method signature.
1public void method1(int b) { 2 System.out.println("Called method1 with integer " + b); 3} 4 5public void method2(int v) { 6 System.out.println("Called method2 with integer " + v); 7} 8 9public void method3(int a) { 10 System.out.println("Called method3 with integer " + a); 11}
The next step is to create variables of the wrapping interface and assign methods to them. The variables will act as a function pointer to be stored or executed.
1// Create a variable of the interface and assign 2// the method references 3FunctionPointer pointer1 = this::method1; 4FunctionPointer pointer2 = this::method2; 5 6// Call both methods using their "pointer" 7pointer1.methodSignature(3); 8pointer2.methodSignature(2); 9 10// Reassign and call pointer 1 11pointer1 = this::method3; 12 13pointer1.methodSignature(5);
1Called method1 with integer 3 2 3Called method2 with integer 2 4 5Called method3 with integer 5
Using Lambdas
Method references can be assigned using lambdas.
1// Create a method reference and assign a methods using a lambda. 2FunctionPointer pointer1 = 3 (a) -> System.out.println("Called pointer1 with int " + a); 4 5FunctionPointer pointer2 = 6 (b) -> System.out.println("Called pointer2 with int " + b);
Array of Function Pointers
The functionality of an array of method references can be emulated by creating an array of the wrapping interface.
1// Create an array of "pointers" 2FunctionPointer[] functionPointersArray = new FunctionPointer[3]; 3 4// Assign methods 5functionPointersArray[0] = this::method1; 6functionPointersArray[1] = this::method2; 7functionPointersArray[2] = this::method3; 8 9// Call methods 10functionPointersArray[0].methodSignature(3); 11functionPointersArray[1].methodSignature(4); 12functionPointersArray[2].methodSignature(5);
Function Pointer vs. Direct Call
You may be wondering, is there any penalty for using a method reference over directly calling a method? The answer is yes, but a tiny one.
From the chart above, a direct method call is almost 5x faster than using a method reference because of the extra step to call the lambda than the stored method. Honestly, you probably won't notice the performance penalty, so don't worry about it.
Conclusion
Pointers are variables that point directly to the address of objects instead of passing by value. A function pointer directly points to the address of a function which can decrease memory consumption. Java doesn't have pointers but the behavior using method references or lambdas. Using a method reference is slower than a direct method call but not enough to deter usage of the feature.
Consider signing up for my newsletter or supporting me if this was helpful. Thanks for reading!