Four Types of Method References in Java 8
Fast recall
Quick revision
Core answer
Whether you can categorize method references correctly and understand the subtle difference between bound and unbound instance method references.
Confusing bound versus unbound instance references—bound uses a specific object instance captured from the enclosing scope, while unbound treats the first parameter as the receiver object.
Explain that unbound instance method references are especially useful with streams, where each element becomes the receiver of the method call.
Interview-ready guide
Interview answer
There are four types of method references in Java 8.
First is the static method reference using ClassName colon colon methodName, like Math colon colon max. This calls a static method on a class. Second is the bound instance method reference where you have a specific object and you write object colon colon method.
For example, if I have a String called myString, I can write myString colon colon length, and it'll always call length on that exact string object. Third is the unbound instance method reference, which looks like ClassName colon colon instanceMethod, such as String colon colon toUpperCase. The key difference from bound is that here you don't have a specific object yet—the object comes from the functional interface parameter.
This is super common in streams. When you write names dot stream dot map with String colon colon toUpperCase, each name string in the stream becomes the object that toUpperCase gets called on. Fourth is the constructor reference using ClassName colon colon new, like ArrayList colon colon new.
This creates new instances and is useful for factory patterns. The tricky part for freshers is telling apart bound and unbound instance references. If you see a variable name before the colon colon, that's bound—it's calling the method on that specific object.
If you see a class name, that's unbound, and the object will come from the parameter. This matters a lot in streams where you want each element to be the receiver.
Four Types of Method References in Java 8
Direct Answer
The four types are: static method reference (Math::max), bound instance method reference (str::length using a specific object), unbound instance method reference (String::toUpperCase where the instance comes from the context), and constructor reference (ArrayList::new). Each serves a different use case depending on whether you're calling a static method, instance method on a known object, instance method on a parameter, or a constructor.
Code Example
import java.util.List;
import java.util.function.*;
public class MethodReferenceTypes {
public static void main(String[] args) {
// Type 1: Static method reference - ClassName::staticMethod
BinaryOperator<Integer> maxFinder = Math::max;
System.out.println(maxFinder.apply(5, 10)); // 10
// Type 2: Bound instance method reference - object::instanceMethod
String prefix = "Hello";
Predicate<String> startsWithHello = prefix::startsWith; // prefix is captured
System.out.println(startsWithHello.test("Hel")); // true
// Type 3: Unbound instance method reference - ClassName::instanceMethod
var names = List.of("alice", "bob", "charlie");
names.stream()
.map(String::toUpperCase) // each element becomes the receiver
.forEach(System.out::println);
// Type 4: Constructor reference - ClassName::new
Supplier<List<String>> listFactory = java.util.ArrayList::new;
List<String> newList = listFactory.get();
Function<Integer, List<String>> sizedListFactory = java.util.ArrayList::new;
List<String> capacityList = sizedListFactory.apply(100); // initial capacity
}
}
Common Mistakes & Pitfalls
- Confusing bound and unbound:
String::lengthreceives the String as the functional argument, whilemyString::lengthevaluates and binds one receiver when the reference is created. - Reducing compatibility to parameter count: receiver placement, parameter and return adaptation, overload resolution, and accessibility must all match the target functional interface.
- Binding a null receiver: evaluating a bound reference such as
user::getEmailthrowsNullPointerExceptionimmediately ifuseris null; the failure does not wait for the functional interface to be invoked.
Check your understanding
Answer these without looking back at the article.
- What is the difference between bound and unbound instance method references?
- How does the compiler know which functional interface a method reference targets?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.