Method References in Java
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
ClassName::staticMethod
object::instanceMethod
ClassName::instanceMethod
ClassName::newThe Four Kinds of Method References
| Kind | Syntax | Equivalent lambda |
|---|---|---|
| Static method | Integer::parseInt | s -> Integer.parseInt(s) |
| Instance method of a particular object | System.out::println | x -> System.out.println(x) |
| Instance method of an arbitrary object of a type | String::toUpperCase | s -> s.toUpperCase() |
| Constructor | ArrayList::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.
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"));
}
}Static: 92
Navika
Srihitha
Arbitrary object: ADVITHA
Two parameters: true
Constructor: [Anamaneni]
Record constructor: Student[name=Navika]Explanation:
Integer::parseIntcalls a static method with the lambda's argument.System.out::printlncallsprintlnon one particular object,System.out.String::toUpperCasecalls the method on whatever string is passed in. With two parameters,String::equalsIgnoreCasecalls the method on the first and passes the second.ArrayList::newandStudent::newcall constructors; Java picks the constructor that matches the functional interface.
Example: Method References in Streams
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);
}
}[NAVIKA, ADVITHA, SRIHITHA]
254Explanation: 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
- Easy: Rewrite
names.forEach(n -> System.out.println(n))andlist.stream().map(s -> s.trim())with method references. - Harder: Convert a
List<String>of numbers into aList<Integer>, sort it in reverse withComparator.reverseOrder(), and collect it into aTreeSetcreated withTreeSet::new.
Key Takeaways
Was this tutorial helpful?