In Java 8, a new functionality known as method reference is introduced. This feature allows referencing a method of a functional interface. Method reference offers a streamlined and simplified alternative to lambda expressions. Whenever you find yourself using a lambda expression solely to reference a method, you have the option to substitute it with method reference. The following tutorial elaborates on the concept of method reference in Java.
Types of Method References
There are following types of method references in java:
- Reference to a static method.
- Reference to an instance method.
- Reference to a constructor.
1) Reference to a Static Method
One way to access a static method is by referencing it within the class where it is defined. Below you can find the syntax and an example illustrating how to reference a static method in Java.
Syntax
ContainingClass::staticMethodName
Example 1
In this illustration, a functional interface has been defined, and a static method is being referenced to its functional method called say.
Example
interface Sayable{
void say();
}
public class MethodReference {
public static void saySomething(){
System.out.println("Hello, this is static method.");
}
public static void main(String[] args) {
// Referring static method
Sayable sayable = MethodReference::saySomething;
// Calling interface method
sayable.say();
}
}
Output:
Hello, this is static method.
Example 2
In this instance, we are utilizing a predefined functional interface called Runnable to reference a static method.
Example
public class MethodReference2 {
public static void ThreadStatus(){
System.out.println("Thread is running...");
}
public static void main(String[] args) {
Thread t2=new Thread(MethodReference2::ThreadStatus);
t2.start();
}
}
Output:
Thread is running...
Example 3
Another approach is to utilize predefined functional interfaces to reference methods. In this instance, the BiFunction interface is employed, and its apply method is utilized as shown below.
Example
import java.util.function.BiFunction;
class Arithmetic{
public static int add(int a, int b){
return a+b;
}
}
public class MethodReference3 {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer>adder = Arithmetic::add;
int result = adder.apply(10, 20);
System.out.println(result);
}
}
Output:
Example 4
It is also possible to replace static methods by referencing methods. In this instance, we have created and varied three add methods.
Example
import java.util.function.BiFunction;
class Arithmetic{
public static int add(int a, int b){
return a+b;
}
public static float add(int a, float b){
return a+b;
}
public static float add(float a, float b){
return a+b;
}
}
public class MethodReference4 {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer>adder1 = Arithmetic::add;
BiFunction<Integer, Float, Float>adder2 = Arithmetic::add;
BiFunction<Float, Float, Float>adder3 = Arithmetic::add;
int result1 = adder1.apply(10, 20);
float result2 = adder2.apply(10, 20.0f);
float result3 = adder3.apply(10.0f, 20.0f);
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
}
}
Output:
30
30.0
30.0
2) Reference to an Instance Method
Similar to static methods, instance methods can also be referenced. Below is an example illustrating how to reference an instance method.
Syntax
containingObject::instanceMethodName
Example 1
In this instance, we are discussing non-static methods. Methods can be referenced using a class object or an anonymous object.
Example
interface Sayable{
void say();
}
public class InstanceMethodReference {
public void saySomething(){
System.out.println("Hello, this is non-static method.");
}
public static void main(String[] args) {
InstanceMethodReference methodReference = new InstanceMethodReference(); // Creating object
// Referring non-static method using reference
Sayable sayable = methodReference::saySomething;
// Calling interface method
sayable.say();
// Referring non-static method using anonymous object
Sayable sayable2 = new InstanceMethodReference()::saySomething; // You can use anonymous object also
// Calling interface method
sayable2.say();
}
}
Output:
Hello, this is non-static method.
Hello, this is non-static method.
Example 2
In the upcoming illustration, we are discussing a method that is not static, known as an instance method. The Runnable interface consists of just a single abstract method. Consequently, it can be utilized as a functional interface.
Example
public class InstanceMethodReference2 {
public void printnMsg(){
System.out.println("Hello, this is instance method");
}
public static void main(String[] args) {
Thread t2=new Thread(new InstanceMethodReference2()::printnMsg);
t2.start();
}
}
Output:
Hello, this is instance method
Example 3
In this instance, we are utilizing the BiFunction interface, which is a pre-defined interface featuring a functional method called apply. In this scenario, we are associating the add method with the apply method.
Example
import java.util.function.BiFunction;
class Arithmetic{
public int add(int a, int b){
return a+b;
}
}
public class InstanceMethodReference3 {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer>adder = new Arithmetic()::add;
int result = adder.apply(10, 20);
System.out.println(result);
}
}
Output:
3) Reference to a Constructor
Constructors can be invoked using the new keyword. In this case, we are referencing a constructor through a functional interface.
Syntax
ClassName::new
Example
Example
interface Messageable{
Message getMessage(String msg);
}
class Message{
Message(String msg){
System.out.print(msg);
}
}
public class ConstructorReference {
public static void main(String[] args) {
Messageable hello = Message::new;
hello.getMessage("Hello");
}
}
Output: