foreach-ui logo
codeLanguages
account_treeDSA

Quick Actions

quizlock Random Quiz
trending_uplock Progress
  • 1
  • 2
  • 3
  • 4
  • 5
  • quiz
Java
  • Understand the four types of method references
  • Learn when to use method references vs lambdas
  • Master the :: operator syntax
  • Apply method references in common patterns

Method References

Lambdas made code concise. But sometimes you're just calling an existing method—x -> System.out.println(x). Method references make this even cleaner: System.out::println.

They're shorthand when the lambda only calls one method.

What are Method References?

A method reference is a way to refer to a method without executing it. It uses the :: operator:

// Lambda
Consumer<String> printer1 = s -> System.out.println(s);

// Method reference (equivalent)
Consumer<String> printer2 = System.out::println;

// Both do the same thing
printer1.accept("Hello");  // prints "Hello"
printer2.accept("Hello");  // prints "Hello"

Four Types of Method References

1. Reference to a Static Method

Syntax: ClassName::staticMethodName

// Lambda
Function<String, Integer> parser1 = s -> Integer.parseInt(s);

// Method reference
Function<String, Integer> parser2 = Integer::parseInt;

// Usage
Integer num = parser2.apply("42");  // 42

More examples:

// Math.abs
Function<Integer, Integer> abs = Math::abs;

// String.valueOf
Function<Object, String> toString = String::valueOf;

// Arrays.sort
Consumer<int[]> sorter = Arrays::sort;

2. Reference to an Instance Method of a Particular Object

Syntax: objectReference::instanceMethodName

String prefix = "Hello, ";

// Lambda
Function<String, String> greeter1 = name -> prefix.concat(name);

// Method reference
Function<String, String> greeter2 = prefix::concat;

// Usage
greeter2.apply("World");  // "Hello, World"

More examples:

List<String> names = new ArrayList<>();

// Lambda
Consumer<String> adder1 = name -> names.add(name);

// Method reference
Consumer<String> adder2 = names::add;

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

3. Reference to an Instance Method of an Arbitrary Object of a Particular Type

Syntax: ClassName::instanceMethodName

This one is tricky - the first parameter becomes the object on which the method is called:

// Lambda: s is the object, length() is called on it
Function<String, Integer> lengthFn1 = s -> s.length();

// Method reference: String::length means "call length() on the String"
Function<String, Integer> lengthFn2 = String::length;

// Usage
lengthFn2.apply("hello");  // 5

For comparison methods:

// Lambda: first param is the object, second is the argument
Comparator<String> comp1 = (s1, s2) -> s1.compareToIgnoreCase(s2);

// Method reference
Comparator<String> comp2 = String::compareToIgnoreCase;

// Usage
comp2.compare("Hello", "hello");  // 0

4. Reference to a Constructor

Syntax: ClassName::new

// Lambda
Supplier<ArrayList<String>> listFactory1 = () -> new ArrayList<>();

// Constructor reference
Supplier<ArrayList<String>> listFactory2 = ArrayList::new;

// Usage
List<String> list = listFactory2.get();

With parameters:

// Lambda
Function<String, StringBuilder> sbFactory1 = s -> new StringBuilder(s);

// Constructor reference
Function<String, StringBuilder> sbFactory2 = StringBuilder::new;

// Usage
StringBuilder sb = sbFactory2.apply("Hello");

Method Reference Summary Table

Type Syntax Lambda Equivalent
Static method ClassName::staticMethod x -> ClassName.staticMethod(x)
Instance method (specific object) object::instanceMethod x -> object.instanceMethod(x)
Instance method (arbitrary object) ClassName::instanceMethod x -> x.instanceMethod()
Constructor ClassName::new x -> new ClassName(x)

When to Use Method References

Use Method References When:

  1. The lambda just calls a method with the same parameters:
// Perfect for method reference
list.forEach(s -> System.out.println(s));
list.forEach(System.out::println);  // Better!

names.sort((a, b) -> a.compareToIgnoreCase(b));
names.sort(String::compareToIgnoreCase);  // Better!
  1. You want cleaner, more readable code:
// Clear intent: "convert each to uppercase"
list.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

Keep Lambdas When:

  1. You need to transform parameters:
// Need lambda - parameter order/transformation
BiFunction<String, String, String> fn = (a, b) -> a.substring(0, b.length());
  1. You're calling multiple methods:
// Need lambda - multiple operations
Consumer<String> process = s -> {
    validate(s);
    save(s);
};
  1. The method name would be confusing:
// Lambda is clearer here
Predicate<Integer> isEven = n -> n % 2 == 0;
// vs some hypothetical MathUtils::isEven

Common Patterns

Collection Operations

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

// Printing
names.forEach(System.out::println);

// Sorting
names.sort(String::compareTo);
names.sort(String::compareToIgnoreCase);

// Mapping
List<Integer> lengths = names.stream()
    .map(String::length)
    .collect(Collectors.toList());

// Filtering with method on object
List<String> nonEmpty = strings.stream()
    .filter(s -> !s.isEmpty())  // Can't use method ref here
    .collect(Collectors.toList());

Creating Objects

// Create stream of new objects
List<StringBuilder> builders = names.stream()
    .map(StringBuilder::new)
    .collect(Collectors.toList());

// With Supplier
Supplier<List<String>> listSupplier = ArrayList::new;
List<String> newList = listSupplier.get();

With Comparators

// Sort by property
people.sort(Comparator.comparing(Person::getName));
people.sort(Comparator.comparing(Person::getAge).reversed());

// Multiple criteria
people.sort(Comparator
    .comparing(Person::getLastName)
    .thenComparing(Person::getFirstName));

Method References with Generics

// Works with generic types
Function<List<String>, Integer> sizeGetter = List::size;
BiFunction<List<String>, String, Boolean> containsChecker = List::contains;

// Constructor with generic
Supplier<List<String>> listFactory = ArrayList::new;

Common Mistakes

Trying to Reference Private Methods

public class Example {
    private void helper() { }
    
    public void demo() {
        // This works - same class
        Runnable r = this::helper;
    }
}

class Other {
    public void demo(Example e) {
        // This fails - helper is private
        // Runnable r = e::helper;  // Compilation error!
    }
}

Ambiguous Method References

// If multiple overloaded methods exist, context must resolve it
public static void process(String s) { }
public static void process(Integer i) { }

Consumer<String> c = Example::process;   // OK - unambiguous
Consumer<Integer> c2 = Example::process; // OK - unambiguous
// Consumer<Object> c3 = Example::process; // Error - ambiguous

Method references are shorthand for lambdas that just call a method. Four types: static (Integer::parseInt), bound instance (object::method), unbound instance (String::length), constructor (ArrayList::new). Use when lambda simply delegates to existing method. Keep lambda when you need parameter transformation. Method references often improve readability.

© 2026 forEach. All rights reserved.

Privacy Policy•Terms of Service