Amongst the notable features in Java8, Method Reference adds Shorthand syntax for a lambda expression. In most cases, Lambda expression does nothing more than just calling a single method. If you find yourself doing that most often, its time to look at Method reference. It can be used to replace entire Lambda expression, let’s have a look at following example
class Student { int rollNo; String name; LocalDate birthDate; //Getter and setter goes here. }
The Student class captures basic details like Roll Number, Birth Date and Student name. Let’s define a collection to store some student information
public class StudentApplication { public static void main(String[] args) { List students = new ArrayList<>(); students.add(createStudent("Michael Freit", 122, LocalDate.of(1998, 05, 12))); students.add(createStudent("Jeremy Kahn", 110, LocalDate.of(1998, 01, 03))); students.add(createStudent("Hugo Patrick", 95, LocalDate.of(1998, 03, 24))); students.add(createStudent("Nathan Hendrige", 130, LocalDate.of(1998, 02, 18))); students.add(createStudent("Kate hudson", 117, LocalDate.of(1998, 04, 10))); } private static Student createStudent(String name, int rollNo, LocalDate dateOfBirth) { Student student = new Student(); student.setName(name); student.setRollNo(rollNo); student.setDateOfBirth(dateOfBirth); return student; } }
What if you wish to simply print name of each student from the list. The pre-Java 8 syntax will be like
for(Student s : students){ System.out.println(student.getName()); }
Using Java 8, Lambda expression syntax will look like below
students.stream().map(student -> student.getName()).forEach(s->System.out.println(s));
With Method expression, the code will look like
students.stream().map(Student::getName).forEach(System.out::println);
Notice student -> student.getName()
is replaced with Student::getName
and s->System.out.println(s)
with System.out::println
. In each of the Lambda expression, a single method was replaced with equivalent Method reference. Student::getName
is a method reference of a defined type and System.out::println
is an instance method of PrintStream
object. In addition to that there are two more kinds.
- Static method reference
- Constructor reference
Static method reference
Static method reference requires a name of the class followed by the method name
Class::method
Let’s understand it by writing some code.
public class Library { public static void main(String[] args) { Listshelf = new ArrayList<>(); shelf.add("Blockchain revolution"); shelf.add("Start with WHY?"); shelf.add("Flying without Net"); } private static void printBookName(String name) { System.out.println(name) } }
To print name of each book
Java 7 or before
for(String book : shelf) { printBookName(book); }
Java 8 with lambda
shelf.stream().forEach(s -> printBookName(s));
With Java 8 method reference
shelf.stream().forEach(Library::printBookName);
Constructor with new
This one is very easy, instead of using
new Integer();
use
Integer::new
So based on above examples Method Reference can be summarised as
Kind | Pre-Java 8 | Java 8 |
Static Method | Class.staticMethod(); | Class::staticMethod |
Instance Method | object.instanceMethod() | object::instanceMethod |
Instance Method of Specific Type | sampleMethod(obj, args) { obj.callMe(args); } | ObjectType::callMe |
Constructor | new SomeClass() | SomeClass::new |
That’s not all about Method Reference. Refer below example of how a thread can be created using a Method reference
public class ThreadDemo { public static void main(String[] args) { //Pre-Java 8 Thread t = new Thread(new Runnable(){ public void run(){ ThreadDemo.printName(); } }); t.start(); //Java8-Lambda Thread t2 = new Thread(()-> ThreadDemo.printName()); t2.start(); //Java8-Method reference Thread t3 = new Thread(ThreadDemo::printName); t3.start(); } private static void printName(){ System.out.println("I am inside Thread!!!"); } }
In next article, we will explore more about java.util.function
package and identify how it fits with MethodReference and Lambda.