45. Method References
Method references (::) are shorthand for lambdas that simply call a single existing method โ four kinds: static, bound instance, unbound instance, and constructor references.
Explanation
Method references are syntactic sugar for a lambda that calls one method. They are more readable when the lambda does nothing but forward arguments to an existing method.
Four kinds: - Static: ClassName::staticMethod โ e.g., Integer::parseInt, replaces s -> Integer.parseInt(s). - Bound instance: instance::method โ e.g., "prefix"::concat, replaces s -> "prefix".concat(s); the instance is captured. - Unbound instance: ClassName::instanceMethod โ e.g., String::toUpperCase, replaces s -> s.toUpperCase(); the instance is the first argument. - Constructor: ClassName::new โ e.g., ArrayList::new, replaces () -> new ArrayList<>().
Prefer a method reference whenever the lambda does nothing beyond calling a method โ it reduces noise. Use a lambda when there's any additional logic or argument reordering.
Example
import java.util.Arrays;
import java.util.List;
import java.util.function.*;
import java.util.stream.Collectors;
public class MethodReferences {
static int doubleIt(int x) { return x * 2; }
record Person(String name, int age) {}
public static void main(String[] args) {
// 1. Static method reference
Function<String, Integer> parse = Integer::parseInt; // s -> Integer.parseInt(s)
System.out.println(parse.apply("42")); // 42
List<Integer> nums = List.of(1, 2, 3, 4, 5);
List<Integer> doubled = nums.stream()
.map(MethodReferences::doubleIt) // static ref
.toList();
System.out.println(doubled);
// 2. Bound instance method reference
String prefix = "Hello, ";
Function<String, String> greet = prefix::concat; // s -> prefix.concat(s)
System.out.println(greet.apply("Alice")); // Hello, Alice
// 3. Unbound instance method reference
Function<String, String> upper = String::toUpperCase; // s -> s.toUpperCase()
List<String> names = List.of("alice", "bob", "charlie");
names.stream().map(String::toUpperCase).forEach(System.out::println);
// 4. Constructor reference
Function<String, StringBuilder> sbFactory = StringBuilder::new;
StringBuilder sb = sbFactory.apply("start");
System.out.println(sb);
// Comparator via method reference
var people = List.of(new Person("Charlie", 30), new Person("Alice", 25), new Person("Bob", 35));
people.stream()
.sorted(Comparator.comparing(Person::name)) // unbound ref
.forEach(p -> System.out.println(p.name() + ":" + p.age()));
// println as a consumer
List.of("x", "y", "z").forEach(System.out::println); // bound: System.out::println
}
}Sources
- https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html โ Method references tutorial
- https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/function/package-summary.html โ java.util.function API