Method References

1. What Is a Method Reference?

A method reference is a shorter way to write a lambda when the lambda only calls an existing method.

Syntax:

ClassName::method

Example:

Consumer<String> printer = s -> System.out.println(s);

Can become:

Consumer<String> printer = System.out::println;

Both mean: take a String and print it.


2. When to Use It

Use a method reference when there is no extra logic.

// Lambda
list.forEach(s -> System.out.println(s));

// Method reference
list.forEachprintln;

If extra logic is needed, use a lambda:

list.forEach(s -> System.out.println(s.toUpperCase()));

3. Four Types of Method References

Type Syntax Meaning
Static Class::staticMethod Calls static method
Bound object::method Object already fixed
Unbound Class::method Object provided later
Constructor Class::new Creates an object

4. Static Method Reference

References a static method.

DoubleUnaryOperator sqrt = Math::sqrt;

Same as:

DoubleUnaryOperator sqrt = x -> Math.sqrt(x);
System.out.println(sqrt.applyAsDouble(25)); // 5.0

Pattern:

ClassName::staticMethod

Examples:

Math::sqrt
Math::max
Integer::parseInt

5. Bound Method Reference

The object is already fixed.

Consumer<String> printer = System.out::println;

Same as:

Consumer<String> printer =
    s -> System.out.println(s);

Here:

System.out → fixed object
println    → method

Pattern:

object::instanceMethod

Think: object is already known.


6. Unbound Method Reference

The object is provided later.

Function<String, Integer> length = String::length;

Same as:

Function<String, Integer> length =
    s -> s.length();

Then:

System.out.println(length.apply("Hello")); // 5

The object "Hello" is provided when apply() is called.

Pattern:

ClassName::instanceMethod

Think: object will be provided later.


7. Bound vs Unbound

Bound

String name = "Hello";

Function<String, String> f = name::toUpperCase;

The object is fixed:

name → toUpperCase()

Same as:

() -> name.toUpperCase()

Unbound

Function<String, String> f = String::toUpperCase;

The object is provided later:

f.apply("hello");

Same as:

s -> s.toUpperCase()

Easy Rule

object::method → Bound
Class::method  → Unbound

8. Constructor Reference

ClassName::new references a constructor.

Supplier<ArrayList<String>> supplier =
    ArrayList::new;

Same as:

Supplier<ArrayList<String>> supplier =
    () -> new ArrayList<>();

Then:

ArrayList<String> list = supplier.get();

Constructor with Parameters

Function<Integer, ArrayList<String>> creator =
    ArrayList::new;

Same as:

size -> new ArrayList<>(size);

The functional interface determines which constructor is used.

Pattern:

ClassName::new

9. Common Example with forEach()

List<String> names =
    List.of("Alice", "Bob", "Charlie");

names.forEachprintln;

Same as:

names.forEach(name -> System.out.println(name));

10. Method Reference with Your Own Class

class Person {
    private String name;

    Person(String name) {
        this.name = name;
    }

    String getName() {
        return name;
    }
}

Method reference:

Function<Person, String> getName =
    Person::getName;

Same as:

person -> person.getName();

Usage:

Person p = new Person("John");

System.out.println(getName.apply(p)); // John

Quick Comparison

Lambda Method Reference
x -> Math.sqrt(x) Math::sqrt
x -> System.out.println(x) System.out::println
x -> x.length() String::length
() -> new ArrayList<>() ArrayList::new

Quick Revision

Class::staticMethod      → Static
object::instanceMethod   → Bound
Class::instanceMethod    → Unbound
Class::new                → Constructor

Simple Definition

Method reference = shorter lambda when the lambda only calls an existing method.