In this section, we will learn what the method-reference is and how it works in Java.
Prerequisite: lambda expression in Java.
What is Method Reference in Java? (Method Reference and Lambda Expression)
In the last section, we explained that we can use lambda expression to create the body of an abstract method of a functional interface.
But Java went one step further and now we can use those static or non-static methods that are already defined in a program and use them as the body of an abstract method of a functional interface. This is called method reference.
Note: the target method that we’re referring at, should have the same signature as the target abstract method. This means the return data type, the number of parameters and the data type of those parameters in both methods should be the same.
Types of method reference in Java
- – Reference to a static method.
- – Reference to an object method.
- – Reference to a constructor.
Lambda Reference to a static method in Java
When in a program there’s a static method with the same signature as the abstract method of a function interface, we can use that static method as the replacement of the target abstract method.
Example: reference to a static method
Let’s say we have an interface named `FuncInterface` that has this body:
public interface FuncInterface { void greet(String name); }
Obviously, this is a functional interface (because there’s only one abstract method in it). The return data type of this method is `void` and it takes one argument of type `String`.
Now let’s create a class named `Simple` and put the code below into that file:
public class Simple { public static void sayHi(String name){ System.out.println("Hello "+name); } public static void main(String[] args) { FuncInterface func = Simple::sayHi; } }
In this class, there’s a static method named `sayHi()`. The return data type of this method is `void` and it takes only one argument of type `String`. So if the body of this method matches our need (let’s say it does) we can use this static method as the body of the `greet()` abstract method because both methods have the same signature.
To do that, we use the name of the class + the `::` operator + the name of target static method which in this case is `sayHi`.
So if you look at the `main` method:
FuncInterface func = Simple::sayHi;
Here we’ve set the `sayHi` method to be used anytime the call to the `greet()` method happened via `func` variable.
So let’s call this `greet()` method then and see the output:
public class Simple { public static void sayHi(String name){ System.out.println("Hello "+name); } public static void main(String[] args) { FuncInterface func = Simple::sayHi; func.greet("John"); } }
Output: Hello John
If also there was a method that accepts either an object of a class that implemented a function interface or a lambda expression, we could use directly a reference to static method as the argument of that method.
Example:
public class Simple { public static void sayHi(String name){ System.out.println("Hello "+name); } public static void main(String[] args) { checking(Simple::sayHi); } public static void checking(FuncInterface fc){ fc.greet("Peter"); } }
Output: Hello Peter
Lambda Reference to an object method in Java
Other than static methods, if there’s a non-static method in a class that has the same signature as the target abstract method, we can create an object from that class and use its method as the body of the target abstract method.
Example: reference to an object method in Java
public class Simple { public void sayHi(String name){ System.out.println("Hello "+name); } public static void main(String[] args) { Simple sim = new Simple(); checking(sim::sayHi); } public static void checking(FuncInterface fc){ fc.greet("Peter"); } }
Output: Hello Peter
Note: we’re still using the `FuncInterface` that you saw in the last example.
In the `Simple` class, we have a non-static method named `sayHi` that has the same signature as the `greet` abstract method. But as you can see, this method is not static and so we can’t use the name of the class to refer to this method.
What we can do is that we can create an object from the `Simple` class and use it to refer to this `sayHi` method.
Note: again, we use the `::` operator to point to the target method.
Lambda Reference to a constructor in Java
If there’s a constructor in a class that has the same signature as the target abstract method; it can be used as the body of the abstract method.
Example: reference to a constructor in Java
public class Simple { public Simple(String name, String lastName){ System.out.println("Hello "+ name+ " "+lastName); } public Simple(String name){ System.out.println("Hello "+ name); } public static void main(String[] args) { FuncInterface fc = Simple::new; checking(fc); } public static void checking(FuncInterface fc){ fc.greet("Peter"); } }
Output:
Hello Peter
The `Simpl` class here has two constructors. One of them, though, matches the signature of the `greet()` abstract method. So because there’s a match, we can use this constructor as the body of this method.
All we need to do is to call the `Simple` method + the `::` operator + the keyword `new`. Behind the scene, the compiler will check the constructors of this class and choose the one that fits the signature of the target abstract method (`greet` in this case).