Method references: all four kinds
A method reference is shorthand for a lambda that just calls an existing method. There are four distinct
shapes, and telling them apart is mostly about where the receiver comes from: a fixed class, an already-in-hand
object, an argument supplied at call time, or new itself.
import java.util.*;
import java.util.function.*;
// 1. static method reference -- ClassName::staticMethod
Function<String, Integer> parse = Integer::parseInt;
System.out.println("static: " + parse.apply("42"));
// 2. bound instance method reference -- an object you already have, objectRef::method
String greeting = "hello";
Supplier<Integer> length = greeting::length;
System.out.println("bound instance: " + length.get());
// 3. unbound instance method reference -- ClassName::instanceMethod, receiver becomes the first argument
Function<String, Integer> lengthOf = String::length;
System.out.println("unbound instance: " + lengthOf.apply("world!"));
// 4. constructor reference -- ClassName::new
Function<String, StringBuilder> build = StringBuilder::new;
System.out.println("constructor: " + build.apply("built").reverse());
In practice these show up constantly inside streams, where they're more concise than the equivalent lambda:
record Person(String name, int age) {}
List<Person> people = List.of(new Person("Bob", 30), new Person("Amy", 25));
people.stream().map(Person::name).forEach(System.out::println); // unbound + bound, chained