Java 8 Method References

Overview

In this tutorial, we will learn Java 8 method references with examples.
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 a method reference.
In this post, we will learn what is method reference, what are their benefits, and what are different types of method references.

Kinds of Method References

There are four kinds of method references:

1. Reference to a static method

Example:
ContainingClass::staticMethodName

2. Reference to an instance method of a particular object

Example:
containingObject::instanceMethodName

3. Reference to an instance method of an arbitrary object of a particular type

Example:
ContainingType::methodName

4. 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 to static method in Java.
Syntax :
ContainingClass::staticMethodName 
Example 1: This example shows, how the lambda expression replaced with method refers to the static method.
package com.java.lambda;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

public class MethodRefDemo {

    public static int addition(int a, int b){
        return (a + b);
    }

    public static void main(String[] args) {

        // 2. Method reference to a static method of a class
        Function<Integer, Double> sqrt = (Integer input) -> Math.sqrt(input);
        System.out.println(sqrt.apply(4));
        Function<Integer, Double> sqrtRef = Math::sqrt;
        System.out.println(sqrtRef.apply(4));

        BiFunction<Integer, Integer, Integer> functionLambda = (a, b) -> MethodRefDemo.addition(a, b);
        System.out.println(functionLambda.apply(10, 20));

        BiFunction<Integer, Integer, Integer> function = MethodRefDemo::addition;
        System.out.println(function.apply(10, 20));        
    }
}
Example 2: we can also override static methods by referring to 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 to instance methods also. In the following example, we are describing the process of referring to the instance method. 
Syntax :
containingObject::instanceMethodName 
Example 1: In the following example, we are referring to non-static methods. You can refer to methods by a class object and anonymous object.
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: 
package com.java.lambda;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

@FunctionalInterface
interface Printable{
    void print(String msg);
}

public class MethodRefDemo {

    public void display(String msg){
        System.out.println(msg);
    }

    public static void main(String[] args) {

        // 1. Method reference to an instance method of an object
        MethodRefDemo methodRefDemo = new MethodRefDemo();
        Printable printableLambda = (String msg) -> methodRefDemo.display(msg);
        printableLambda.print("Hello");

        Printable printable = methodRefDemo::display;
        printable.print("Hello");

        // using lambda expression
        Function<String, String> lowerCaseFunction = (String input) -> input.toLowerCase();
        String result = lowerCaseFunction.apply("Java Guides");
        System.out.println(result);

        // using method references
        Function<String, String> lowerCaseFunctionRef = String::toLowerCase;
        String result1 = lowerCaseFunctionRef.apply("Java Guides");
        System.out.println(result1);

    }
}
Example 3: In the following example, we are using BiFunction interface. It is a predefined interface and contains a functional method to 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

Sometimes, we call a method of argument in the lambda expression. In that case, we can use a method reference to call an instance method of an arbitrary object of a specific type.

Syntax :
ContainingType::methodName
Example: 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. 
Syntax :
ClassName::new  
Example 1: The below example demonstrates the usage of method reference to the constructor.
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);  
    }  
}
Example 2: Write the Lambda to convert List into Set and convert Lambda into method reference:
        // 4. reference to a constructor
        List<String> fruits = new ArrayList<>();
        // Adding new elements to the ArrayList
        fruits.add("Banana");
        fruits.add("Apple");
        fruits.add("mango");
        fruits.add("orange");

        // Using lambda expression
        Function<List<String>, Set<String>> f2 = (nameList) -> new HashSet<>(nameList);
        Set<String> set2 = f2.apply(fruits);
        System.out.println(set2);

        // Using Method reference
        Function<List<String>,Set<String>> f3= HashSet::new;
        Set<String> set = f3.apply(fruits);
        System.out.println(set);

Source code on GitHub

The source code of this post is available on GitHub Repository.

Related Java 8 Top Posts

Comments