Mastery
Mastery/Java/D. Streams & functional interfaces
T1 · high-leverage

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.

java
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:

java
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

Interview angle

Interviewers use "which of these four kinds of method reference is this?" as a quick, low-stakes fluency check when reviewing stream-heavy code — being able to name and explain the difference between a bound and unbound instance reference in particular shows real comfort with the functional-interface machinery, not just pattern-matching syntax you've seen before.

In the industry

Method references are near-universal in idiomatic modern Java stream pipelines specifically because they're more concise and often clearer than the equivalent lambda (Person::name vs p -> p.name()). Code review at teams with a strong functional-Java style will often suggest converting a trivial pass-through lambda into the equivalent method reference; the reverse — an unnecessarily verbose lambda where a reference would do — is a common, gentle style comment.