Java 8 Method References
Method References
As we have seen in Java 8 Lambda expressions example Java 8 introduced the concept of Functional Interfaces, which in turn may be implemented by the means of lambda expressions.
As a reminder, a Functional Interface is an interface containing a single abstract method, ie. a method that is not implemented.
Considering the following Functional Interface:public interface Operation<I, O> { O calculate(I input); }And the following class:
public class Calculator { public static int square(int a) { return a * a; } }
We may use the functional interface to get a reference to the Calculator static method:
Operation<Integer, Integer> operation = Calculator::square; // Prints the value 9 System.out.println(operation.calculate(3));
We may get references to any existing static method that matches our Functional Interface:
Operation<String, Integer> operation = Integer::parseInt; // Prints the integer 9 System.out.println(operation.calculate("34"));
It is also possible to get references to instance methods. Let's change our Calculator class:
public class Calculator { int a = 4; public int sum(int b) { return a + b; } public static int square(int a) { return a * a; } }
We may get a reference to the sum instance method:
Calculator calculator = new Calculator(); Operation<Integer, Integer> operation = calculator::sum; // Prints the value 7 System.out.println(operation.calculate(3));
Arbitrary instance methods may also be referenced:
Operation<String, Integer> operation = String::length; // Prints the value 11 System.out.println(operation.calculate("Hello World"));
The compiler will expect that a String instance is passed into our method reference. Since length returns an integer, it will perfectly match the Functional Interface we declared in order to hold the method reference (input of type String and output of type Integer).
Finally we may also have references to Constructor methods. Considering the following class:
public class Person { private String name; private int age; public Person(String name) { this.name = name; } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
And a Functional Interface that represents a person factory:
public interface PersonFactory { Person producePerson(String name); }
We may reference the Constructor using a method reference:
PersonFactory personFactory = Person::new; Person person = personFactory.producePerson("John Smith"); // Prints "John Smith" System.out.println(person.getName());
The compiler will match the Functional Interface method producePerson(String name) with the single argument constructor of our class Person.