Method References
Method References are a special type of syntactic sugar introduced in Java 8. They provide a shorter, more readable alternative to Lambda expressions when the lambda expression does absolutely nothing except call an existing method.
The syntax uses a double-colon :: operator to separate the class/object name from the method name.
The Core Concept
If your lambda expression looks like this:
str -> System.out.println(str)
You are taking an argument (str) and simply passing it straight into another method (println). Because the compiler is smart enough to figure out that the argument should be passed to the method, you can rewrite it using a Method Reference like this:
System.out::println
Types of Method References
There are four primary types of Method References in Java.
1. Reference to a Static Method
Syntax: ClassName::staticMethodName
import java.util.function.Function;
public class LabMethodRef1 {
public static void main(String[] args) {
// Using a Lambda
Function<String, Integer> parseLambda = (str) -> Integer.parseInt(str);
// Using a Method Reference!
Function<String, Integer> parseRef = Integer::parseInt;
System.out.println(parseRef.apply("100")); // Output: 100
}
}
2. Reference to an Instance Method of a Particular Object
Syntax: objectRef::instanceMethodName
import java.util.function.Consumer;
public class LabMethodRef2 {
public static void main(String[] args) {
// System.out is an object of PrintStream!
// Using a Lambda
Consumer<String> printLambda = (str) -> System.out.println(str);
// Using a Method Reference!
Consumer<String> printRef = System.out::println;
printRef.accept("Hello World!");
}
}
3. Reference to an Instance Method of an Arbitrary Object of a Particular Type
Syntax: ClassName::instanceMethodName
This one is slightly confusing. It is used when the method you want to call belongs to the object that is passed as the argument to the lambda.
import java.util.function.Function;
public class LabMethodRef3 {
public static void main(String[] args) {
// Using a Lambda.
// Notice how 'str' is the argument, and we are calling a method ON 'str'
Function<String, String> lowerLambda = (str) -> str.toLowerCase();
// Using a Method Reference!
// We refer to the class of the argument (String) and the method to call.
Function<String, String> lowerRef = String::toLowerCase;
System.out.println(lowerRef.apply("JAVA")); // Output: java
}
}
4. Reference to a Constructor
Syntax: ClassName::new
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class LabMethodRef4 {
public static void main(String[] args) {
// Using a Lambda
Supplier<List<String>> listLambda = () -> new ArrayList<>();
// Using a Constructor Reference!
Supplier<List<String>> listRef = ArrayList::new;
List<String> myList = listRef.get();
}
}
[!TIP] You are never strictly required to use a Method Reference instead of a Lambda. However, most modern IDEs (like IntelliJ or Eclipse) will automatically highlight Lambdas that can be converted into Method References and suggest the change, as it is considered a best practice for clean code.