I was exploring the Java 8 source and found this particular part of code very surprising:
//defined in IntPipeline.java
@Override
public fin
It seems its little late but here are my two cents. A lambda expression is used to create anonymous methods. It does nothing but call an existing method, but it is clearer to refer to the method directly by its name. And method reference enables us to do that using method-reference operator ::
.
Consider the following simple class where each employee has a name and grade.
public class Employee {
private String name;
private String grade;
public Employee(String name, String grade) {
this.name = name;
this.grade = grade;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
Suppose we have a list of employees returned by some method and we want to sort the employees by their grade. We know we can make use of anonymous class as:
List employeeList = getDummyEmployees();
// Using anonymous class
employeeList.sort(new Comparator() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.getGrade().compareTo(e2.getGrade());
}
});
where getDummyEmployee() is some method as:
private static List getDummyEmployees() {
return Arrays.asList(new Employee("Carrie", "C"),
new Employee("Fanishwar", "F"),
new Employee("Brian", "B"),
new Employee("Donald", "D"),
new Employee("Adam", "A"),
new Employee("Evan", "E")
);
}
Now we know that Comparator is a Functional Interface. A Functional Interface is the one with exactly one abstract method (though it may contain one or more default or static methods). Lambda expression provides implementation of @FunctionalInterface
so a functional interface can have only one abstract method. We can use lambda expression as:
employeeList.sort((e1,e2) -> e1.getGrade().compareTo(e2.getGrade())); // lambda exp
It seems all good but what if the class Employee
also provides similar method:
public class Employee {
private String name;
private String grade;
// getter and setter
public static int compareByGrade(Employee e1, Employee e2) {
return e1.grade.compareTo(e2.grade);
}
}
In this case using the method name itself will be more clear. Hence we can directly refer to method by using method reference as:
employeeList.sort(Employee::compareByGrade); // method reference
As per docs there are four kinds of method references:
+----+-------------------------------------------------------+--------------------------------------+
| | Kind | Example |
+----+-------------------------------------------------------+--------------------------------------+
| 1 | Reference to a static method | ContainingClass::staticMethodName |
+----+-------------------------------------------------------+--------------------------------------+
| 2 |Reference to an instance method of a particular object | containingObject::instanceMethodName |
+----+-------------------------------------------------------+--------------------------------------+
| 3 | Reference to an instance method of an arbitrary object| ContainingType::methodName |
| | of a particular type | |
+----+-------------------------------------------------------+--------------------------------------+
| 4 |Reference to a constructor | ClassName::new |
+------------------------------------------------------------+--------------------------------------+