Method References — All Four Types
Use method references for concise lambda expressions: static, instance, arbitrary object, and constructor.
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class MethodRefs {
// 1. Static method reference: ClassName::staticMethod
static int square(int n) { return n * n; }
// 2. Instance method of a particular object: instance::method
static class Printer {
String prefix;
Printer(String prefix) { this.prefix = prefix; }
void print(String msg) { System.out.println(prefix + msg); }
}
// 3. Instance method of an arbitrary object: ClassName::instanceMethod
// Used when the stream element IS the object to call the method on
// 4. Constructor reference: ClassName::new
record User(String name) {}
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<String> names = List.of("Alice", "bob", "Carol");
// 1. Static method ref
List<Integer> squares = numbers.stream()
.map(MethodRefs::square) // instead of n -> square(n)
.toList();
// Also: Integer::parseInt, Math::abs, String::valueOf
List<Integer> parsed = List.of("1", "2", "3").stream()
.map(Integer::parseInt)
.toList();
// 2. Instance method of specific object
Printer logger = new Printer("[LOG] ");
names.forEach(logger::print); // instead of n -> logger.print(n)
// 3. Instance method of arbitrary object (first param becomes `this`)
List<String> upper = names.stream()
.map(String::toUpperCase) // instead of s -> s.toUpperCase()
.toList();
List<String> sorted = names.stream()
.sorted(String::compareToIgnoreCase) // (a, b) -> a.compareToIgnoreCase(b)
.toList();
// 4. Constructor reference
List<User> users = names.stream()
.map(User::new) // instead of name -> new User(name)
.toList();
// With functional interfaces
Function<String, User> factory = User::new;
Supplier<List<String>> listFactory = ArrayList::new;
BiFunction<String, String, String> concat = String::concat;
System.out.println(squares); // [1, 4, 9, 16, 25]
System.out.println(upper); // [ALICE, BOB, CAROL]
System.out.println(users); // [User[name=Alice], ...]
}
}Use Cases
- Concise functional-style code with method references
- Stream pipeline operations
- Factory patterns with constructor references
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
Functional Interfaces and Lambda Patterns
Use built-in and custom functional interfaces: Predicate, Function, Consumer, Supplier, and composition.
Best for: Composable validation and filtering logic
Checked Exception Wrapping Utilities
Wrap checked exceptions for use in lambdas and streams: sneaky throws, functional wrappers, and Either.
Best for: Using checked-exception methods in lambda expressions
Java Streams — Filter, Map, Collect
Process collections with Java Streams: filter, map, flatMap, reduce, and collect to lists or maps.
Best for: Transforming and filtering collections
Strategy Pattern with Lambdas
Implement the Strategy pattern using interfaces and Java lambdas for flexible algorithm selection.
Best for: Swappable pricing or discount algorithms