Java 8 Method References

1. Overview

Java provides a new feature called method reference in Java 8. Method reference is used to refer method of the functional interface. It is a compact and easy form of a lambda expression. Each time when you are using a lambda expression to just referring a method, you can replace your lambda expression with method reference.
In this post, we will learn what is method reference, what are its benefits and what are different types of method references.

2. Kinds of Method References

There are four kinds of method references:
  1. Reference to a static method
Example:
ContainingClass::staticMethodName
  1. Reference to an instance method of a particular object
Example:
containingObject::instanceMethodName
  1. Reference to an instance method of an arbitrary object of a particular type
Example:
ContainingType::methodName
  1. Reference to a constructor
Example:
ClassName::new
Let's discuss these method references one by one with examples.

1. Reference to a Static Method

You can refer to the static method defined in the class. Following is the syntax and example which describe the process of referring static method in Java.
Syntex :
ContainingClass::staticMethodName 
Example 1: This example shows, how the lambda expression replaced with method refer static method.
public class ReferenceToStaticMethod {

 // Syntex : ContainingClass::staticMethodName
 public static void main(String[] args) {
  
  // Using lambda expression
  Thread thread = new Thread(() -> System.out.println("Thread is running using lambda..."));
  thread.start();
  
  // using predefined functional interface Runnable to refer static method
  Thread t2 = new Thread(ReferenceToStaticMethod::ThreadStatus);
  t2.start();
 }

 public static void ThreadStatus() {
  System.out.println("Thread is running...");
 }
}
Example 2: we can also override static methods by referring methods. In the following example, we have defined and overloaded three add methods.
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 ReferenceToStaticMethod2 {
 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);
 }
}

2. Reference to an Instance Method

like static methods, you can refer instance methods also. In the following example, we are describing the process of referring to the instance method. Syntex :
containingObject::instanceMethodName 
Example 1: In the following example, we are referring to non-static methods. You can refer methods by a class object and anonymous object.
// Syntex : containingObject::instanceMethodName 
public class ReferenceToInstanceMethod {

 public void saySomething() {
  System.out.println("Hello, this is non-static method.");
 }

 public static void main(String[] args) {
  // Creating object
  ReferenceToInstanceMethod methodReference = new ReferenceToInstanceMethod();
  // Referring non-static method using reference
  Sayable sayable = methodReference::saySomething;
  // Calling interface method
  sayable.say();
  // Referring non-static method using anonymous object
  
  // You can use  anonymous object also
  Sayable sayable2 = new ReferenceToInstanceMethod()::saySomething; 
  // Calling interface method
  sayable2.say();
 }
}

interface Sayable {
 void say();
}
Example 2: In the following example, we are referring instance (non-static) method. Runnable interface contains only one abstract method. So, we can use it as a functional interface.
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();       
    }  
}
Example 3: In the following example, we are using BiFunction interface. It is a predefined interface and contains a functional method apply(). Here, we are referring to add a method to apply method.
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);
 }
}

3. Reference to an Instance Method of an Arbitrary Object of a Particular Type

Syntex :
ContainingType::methodName
The following is an example of a reference to an instance method of an arbitrary object of a particular type:
String[] stringArray = { "Barbara", "James", "Mary", "John",
    "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);

4. Reference to a Constructor

You can refer to a constructor by using the new keyword. Here, we are referring constructor with the help of a functional interface. 
Syntex :
ClassName::new  
Example :
public class ReferenceToConstructor {
  public static void main(String[] args) {  
         Messageable hello = Message::new;  
         hello.getMessage("Hello");  
 }
}

interface Messageable{  
    Message getMessage(String msg);  
}  

class Message{  
    Message(String msg){  
        System.out.print(msg);  
    }  
}

Comments

Post a Comment