Method Reference in Java


Reading time: 30 minutes | Coding time: 10 minutes

In this article we will cover the Method Reference which is a continuation of Lambda Expressions. Method reference introduced in Java 8 release along with lambda expression as a mechanism to further shorten the lambda expressions containing a method call.

Basically a lambda expression is an anonymous function that can be referenced by a Functional Interface. If the lambda expression is used to call any existing named methods like instance methods, static methods or even constructors, we can replace the lambda expression by method reference and named methods can then be referenced by the Functional Interface.

Let’s get a clear picture of method reference through a basic program that contains two classes Employee and MethodReference.

import java.util.function.Function;

public class MethodReference{
    public static void main(String[] args) {
        Employee employee = new Employee("John", 20);

        Function<Employee, String> getEmpName = emp -> employee.getName(); // Lambda Function access name of an employee
        
        String empName = getEmpName.apply(employee); // invoking the apply method to excecute the Lambda Function.
        
        System.out.println(empName);
    }
}

class Employee{

    String name;
    int age;

    public Employee(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String getName(){
        return name;
    }

    public int getAge(){
        return age;
    }
    
}

Inside the class MethodReference you can see the Employee instance employee and a lambda expression definition to access the name property of any of the Employee object. The target type chosen for the lambda expression is the Functional Interface, Function from the package java.util.function, which contains the abstract method declaration called apply in the form R apply(T t).
apply() method can receive a generic input and returns a generic result which exactly matches our lambda expression definition.

Now we will see how we can shorten the above lambda expression by method reference.

Function<Employee, String> getEmpName = Employee :: getName;

String empName = getEmpName.apply(employee); 

Here the call to the instance method inside the lambda expression is referenced by class name using the operator :: . We can pass any object of type Employee to this lambda expression by invoking the apply method.
When you replace a lambda expression with a method reference you don't have to explicitly mention the arguments that are being passed there; instead, you can just give class name/object name and method to be referred separated by :: operator.

Type of method references

There are four types of method references available.

  • Reference to a static method
  • Reference to an instance method of any particular object
  • Reference to an instance method of an arbitrary object of a particular type
  • Reference to a constructor

1. Reference to a static method

If a lambda expression is to call a static method of a class, then you can modify the lambda expression with a method reference using the following syntax.

<classname> :: <static method name>;

For example, let’s add a static method to the above MethodReference class and define a lambda expression in the form of static method reference.

public class MethodReference(){

    public static void main(String[] args){
    
        Employee employee = new Employee("John", 20);
    
        Function<Integer,Boolean> ageBelowThirty = MethodReference :: isAgeBelowThirty; //static method reference
    
        Boolean ageLimit = ageBelowThirty.apply(employee.getAge());
        
        System.out.println(ageLimit);
        
    }
    
    public static boolean isAgeBelowThirty(int age){
        if(age<30)
            return true;
        else
            return false;
    }
}

We have defined a new static method isAgeBelowThirty and called it in a method reference, which then referenced by a Functional Interface.

2. Reference to an instance method of any particular object

Suppose we have a lambda expression in the following form.

Supplier<String> emp1Name = () -> employee1.getName();

This lambda expression returns name property of the prticular object employee1 of the class Employee. The target type is selected as the Functional Interface Supplier from package java.util.function, which has got abstract method T get().

The method get() matches the defined lambda expression that has no argument and returns a result.

This lambda expression can be modified as a method reference as shown below.

Supplier<String> emp1Name = employee1 :: getName; // referring to the instance method of employee1 object

System.out.println(emp1Name.get());

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

You have already seen this type of method reference, at the very beginning, when we started to explore what method reference is. Let’s take the same example again here.

Function<Employee, String> getEmpName = Employee :: getName;

String empName = getEmpName.apply(employee); 

In this type of method reference, we have to mention the class name followed by the instance method name. While invoking the Functional Interface abstract method we can pass the object for which the instance method needs to be executed.

4. Reference to a constructor

Like instance methods and static methods, a constructor can also be referenced in the following form.

<classname> :: new;

The constructor of a class is executed when an instance of that class being created, using the new operator. We can create a new Employee object using method reference as shown below.

BiFunction<String, Integer, Employee> newEmployee = Employee::new;

Employee employee = newEmployee.apply("Anna", 30);

Target type selected here is the Functional Interface BiFunction from the package java.util.function. The abstract method of BiFunction is in the form R apply(T t, U u). It takes two generic arguments and returns a generic result, which matches our constructor method reference. We have passed two input arguments to the method reference and the result is a newly created Employee object.

Further Readings and References

  1. docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

  2. iq.opengenus.org/lambda-expression-java