What Is a Method Reference in Java 8?
Fast recall
Quick revision
Core answer
System.out::println, String::trim, or ArrayList::new. It can replace a compatible lambda that simply invokes an existing method or constructor. Use it when the name and target type make the behavior clearer; parameter adaptation and overload resolution must still succeed.Whether you understand that method references are syntactic sugar over lambdas and recognize when they improve readability.
Thinking method references are a completely different feature from lambdas rather than just a more concise syntax for the same thing.
Explain that method references and compatible lambdas express the same functional-interface behavior, while bytecode shape and performance are implementation details rather than a language guarantee.
Interview-ready guide
Interview answer
A method reference is a concise way to name an existing method or constructor where a functional interface is expected. For example, String::toUpperCase can replace s -> s.toUpperCase(), and ArrayList::new can replace a lambda that only constructs an ArrayList. The target functional-interface type supplies the context, and the compiler still has to resolve a compatible overload, receiver, parameters, and return. A compatible reference and lambda express the same behavior here, but Java does not promise identical bytecode or performance. I use the reference when the name makes the operation clear and keep the lambda when explicit parameters or extra logic are easier to read.
What Is a Method Reference in Java 8
Direct Answer
A method reference is a target-typed expression such as System.out::println, String::trim, or ArrayList::new. It can replace a compatible lambda that simply invokes an existing method or constructor. Use it when the name and target type make the behavior clearer; parameter adaptation and overload resolution must still succeed.
Code Example
import java.util.List;
import java.util.function.Function;
public class MethodReferenceDemo {
public static void main(String[] args) {
List<String> names = List.of("alice", "bob", "charlie");
names.stream()
.map(name -> name.toUpperCase())
.forEach(result -> System.out.println(result));
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
Function<String, Integer> lambda = s -> s.length();
Function<String, Integer> reference = String::length;
System.out.println(lambda.apply("test"));
System.out.println(reference.apply("test"));
}
}
The paired forms have the same functional result in this example. Their bytecode and runtime cost are implementation details, so the code makes no performance claim.
Common Mistakes & Pitfalls
- Assuming identical bytecode or performance: a compatible lambda and method reference express the same functional-interface behavior here, but Java does not promise one translation or timing.
- Forcing method references everywhere: if
(x) -> service.process(x, DEFAULT_MODE)is clearer than adding a wrapper only to reference it, keep the lambda. - Mismatching the target function type: parameter adaptation, overload resolution, accessibility, and return compatibility all have to succeed; it is more precise than merely counting parameters.
Check your understanding
Answer these without looking back at the article.
- What are the four types of method references?
- Can you always replace a lambda with a method reference?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.