Method References in Java

Naveen AnamaneniUpdated · 4 min read

A method reference in Java is a shorter way to write a lambda expression that does nothing but call an existing method. It uses the :: operator, for example String::length instead of s -> s.length(), or System.out::println instead of x -> System.out.println(x). Method references make code shorter and often easier to read. In this lesson, you will learn the four kinds of method references and when to use them.

Syntax

Syntax
ClassName::staticMethod
object::instanceMethod
ClassName::instanceMethod
ClassName::new

The Four Kinds of Method References

KindSyntaxEquivalent lambda
Static methodInteger::parseInts -> Integer.parseInt(s)
Instance method of a particular objectSystem.out::printlnx -> System.out.println(x)
Instance method of an arbitrary object of a typeString::toUpperCases -> s.toUpperCase()
ConstructorArrayList::new() -> new ArrayList<>()

The third kind is the trickiest: the first parameter of the lambda becomes the object the method is called on. With two parameters, as in String::compareTo, it means (a, b) -> a.compareTo(b).

Example: All Four Kinds

Let's see an example of each kind.

MethodRefs.java▶ Try it
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
 
public class MethodRefs {
    record Student(String name) { }
 
    public static void main(String[] args) {
        Function<String, Integer> parse = Integer::parseInt;
        System.out.println("Static: " + (parse.apply("91") + 1));
 
        List<String> names = List.of("Navika", "Srihitha");
        names.forEach(System.out::println);
 
        Function<String, String> upper = String::toUpperCase;
        System.out.println("Arbitrary object: " + upper.apply("advitha"));
 
        BiFunction<String, String, Boolean> same = String::equalsIgnoreCase;
        System.out.println("Two parameters: " + same.apply("NAVIKA", "navika"));
 
        Supplier<List<String>> newList = ArrayList::new;
        List<String> list = newList.get();
        list.add("Anamaneni");
        System.out.println("Constructor: " + list);
 
        Function<String, Student> make = Student::new;
        System.out.println("Record constructor: " + make.apply("Navika"));
    }
}
Output
Static: 92
Navika
Srihitha
Arbitrary object: ADVITHA
Two parameters: true
Constructor: [Anamaneni]
Record constructor: Student[name=Navika]

Explanation:

  • Integer::parseInt calls a static method with the lambda's argument.
  • System.out::println calls println on one particular object, System.out.
  • String::toUpperCase calls the method on whatever string is passed in. With two parameters, String::equalsIgnoreCase calls the method on the first and passes the second.
  • ArrayList::new and Student::new call constructors; Java picks the constructor that matches the functional interface.

Example: Method References in Streams

StreamRefs.java▶ Try it
import java.util.Comparator;
import java.util.List;
 
public class StreamRefs {
    public static void main(String[] args) {
        List<String> names = List.of("srihitha", "navika", "advitha");
        List<String> result = names.stream()
            .map(String::toUpperCase)
            .sorted(Comparator.comparing(String::length))
            .toList();
        System.out.println(result);
 
        int total = List.of("91", "78", "85").stream()
            .mapToInt(Integer::parseInt)
            .sum();
        System.out.println(total);
    }
}
Output
[NAVIKA, ADVITHA, SRIHITHA]
254

Explanation: String::toUpperCase, String::length and Integer::parseInt replace three small lambdas, and the pipeline reads almost like a sentence.

Common Mistakes

Adding parentheses: String::length(). A method reference names the method; it doesn't call it.

Using a method reference when the method is overloaded in a confusing way. If the compiler reports ambiguity, write the lambda instead.

Expecting System.out::println to be created fresh each time. It captures System.out once, when the reference is evaluated.

Interview Corner

What are method references, and what kinds are there?

A method reference is a compact lambda that calls one existing method, written with ::. There are four kinds: a reference to a static method (Integer::parseInt), to an instance method of a particular object (System.out::println), to an instance method of an arbitrary object of a type, where the first lambda argument becomes the receiver (String::toUpperCase), and to a constructor (ArrayList::new).

Practice

  1. Easy: Rewrite names.forEach(n -> System.out.println(n)) and list.stream().map(s -> s.trim()) with method references.
  2. Harder: Convert a List<String> of numbers into a List<Integer>, sort it in reverse with Comparator.reverseOrder(), and collect it into a TreeSet created with TreeSet::new.

Quick check: Method references

4 questions
1Which lambda equals String::length?
2What kind of reference is System.out::println?
3What does ArrayList::new refer to?
4What does String::compareTo mean as a Comparator?

Key Takeaways

Was this tutorial helpful?

Lesson 310 of 482