method::reference |
If an interface has only one abstract method, it can be turned into functional interface. The calling code can pass in a lambda expression as the implementation of the functional interface.
If the lambda expression do nothing but calls one method/function, we are actually dealing with the named function. The lambda expression can be even shorter. Java 8 added syntax supporting for it -- you can now reference a function with class/objectname::functionname, which is not an object reference, and can only be assigned to functional interface.
There are 4 types of method references.
- Reference to a static method -- class-name::static-method-name.
- Reference to an instance method of an arbitrary object -- class-name::instance-method-name
- Reference to an instance method of a particular object -- object-name::instance-method-name
- Reference to a constructor -- class-name::new
OCPJP>cat MethodRefTester.java
import java.util.*;
import java.util.function.*;
public class MethodRefTester {
public static void main(String...args) {
System.out.println("constructor reference");
BiFunction<String, Integer, Employee> hireF = Employee::new;
Employee mike = hireF.apply("Mike", 100000);
System.out.println(mike.getName());
System.out.println("particular object method reference");
Supplier<String> nameF = mike::getName;
System.out.println(nameF.get());
IntFunction<Integer> raiseF = mike::raise;
System.out.println(raiseF.apply(10000));
System.out.println("static reference");
Supplier<String> getCompanyF = Employee::getCompany;
System.out.println(getCompanyF.get());
System.out.println("Arbitrary object method reference");
Comparator<Employee> isEarlierF = Employee::isEarlier;
Employee sam = hireF.apply("Sam", 140000);
System.out.println(isEarlierF.compare(mike, sam));
System.out.println(isEarlierF.compare(sam, mike));
System.out.println("Functional Interface's abstract method takes 2 parameters with the same type");
TestInterface<Employee> arbitary = Employee::isEarlier;
System.out.println(arbitary.ok(mike, sam));
System.out.println(arbitary.ok(sam, mike));
}
}
@FunctionalInterface
interface TestInterface<R> {
int ok(R a, R b);
}
class Employee {
private String name = "";
private static int ID = 0;
private int id = 0;
private static String COMPANY = "xyz.com";
private int salary = 100000;
public Employee(String name, int salary) {
this.name = name;
this.id = ID++;
this.salary = salary;
}
//provider
public static String getCompany() {
return COMPANY;
}
//provider
public String getName() {
return this.name;
}
//function
public int raise(int delta) {
this.salary += delta;
return this.salary;
}
//Comparator
public int isEarlier(Employee that) {
if(this.id < that.id) {
return 1;
} else {
return -1;
}
}
}
OCPJP>
OCPJP>javac MethodRefTester.java
OCPJP>java MethodRefTester
constructor reference
Mike
particular object method reference
Mike
110000
static reference
xyz.com
Arbitrary object method reference
1
-1
Functional Interface's abstract method takes 2 parameters with the same type
1
-1
OCPJP>