skip to content

Method Reference Kinds

Static, bound instance, unbound instance and constructor references, plus the array-constructor form. The unbound form (String::length, where the first argument becomes the receiver) is the one interviewers reliably ask you to explain.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What are the four kinds of method references in Java, and how is each written?

level: juniorimportance: must knowfreq 72%

answer

  1. Static / bound / unbound / constructor
  2. Bound = receiver fixed; unbound = receiver is first arg
  3. System.out::println vs String::toUpperCase
  4. ClassName::new and int[]::new
  5. Always shorthand for a one-call lambda

basics

~10 s

A method reference is shorthand for a lambda that just calls one method. The four kinds are: static (Class::staticMethod), bound instance (object::method), unbound instance (Class::instanceMethod), and constructor (Class::new).

solid answer

~40 s

A method reference (the :: operator) is concise syntax for a lambda whose body just calls an existing method. There are four forms. Static: ClassName::staticMethod, e.g. Integer::parseInt. Bound instance: instance::method, where the receiver object is fixed/captured at the point of the reference, e.g. System.out::println. Unbound instance: ClassName::instanceMethod, where the receiver is supplied as the first argument at call time, e.g. String::toUpperCase. Constructor: ClassName::new, which creates a new instance, e.g. ArrayList::new. There is also the array-constructor variant int[]::new. Each compiles to the same kind of functional-interface instance a lambda would, and is chosen for readability when no extra arguments or logic are needed.

go deeper

for a junior

Can name the four forms and give one example of each, and knows :: is shorthand for a one-call lambda.

for a middle

Can explain the bound-vs-unbound distinction and which functional interface each form satisfies.

for a senior

Can articulate how the receiver-as-first-parameter rule maps to interfaces like Comparator and Function, and the array-constructor variant.

for a principal

Can reason about overload/target-type resolution, ambiguity cases, capture semantics of bound references, and guide when a reference helps vs. hurts readability in an API.

## What problem method references solve A **lambda expression** in Java is an inline anonymous function, e.g. `s -> s.length()`. A **functional interface** is an interface with exactly one abstract method (e.g. `Function<T,R>` with `R apply(T)`, `Supplier<T>` with `T get()`, `Consumer<T>` with `void accept(T)`). A lambda or method reference is an *implementation* of that single abstract method. Very often a lambda does nothing but forward its arguments to an already-existing method: `s -> Integer.parseInt(s)` or `s -> s.toUpperCase()`. A **method reference**, written with the `::` operator, is a shorthand for exactly that pattern: "don't write a wrapper lambda, just point at the method I want to call." ## The four kinds **1. Reference to a static method** — `ClassName::staticMethod`. Equivalent lambda: `args -> ClassName.staticMethod(args)`. Example: `Integer::parseInt` is the same as `s -> Integer.parseInt(s)`. It satisfies `Function<String,Integer>`. **2. Reference to an instance method of a *particular* object (bound)** — `instance::method`. The **receiver** (the object the method runs on) is **fixed/captured** when you write the reference. Equivalent lambda: `args -> instance.method(args)`. Example: `System.out::println` captures the specific `System.out` object; it is the same as `x -> System.out.println(x)`. Satisfies `Consumer<T>`. Because the receiver is captured, the reference holds onto that object. **3. Reference to an instance method of an *arbitrary* object of a type (unbound)** — `ClassName::instanceMethod`. Here the receiver is **not** fixed; it is supplied as the **first parameter** at call time. Equivalent lambda: `(receiver, otherArgs) -> receiver.method(otherArgs)`. Example: `String::toUpperCase` is the same as `s -> s.toUpperCase()`; it satisfies `Function<String,String>` where the single argument *is* the receiver. `String::compareTo` satisfies `Comparator<String>` = `(a,b) -> a.compareTo(b)`: the first param is the receiver, the second is the method argument. **4. Reference to a constructor** — `ClassName::new`. Equivalent lambda: `args -> new ClassName(args)`. Example: `ArrayList::new` satisfies `Supplier<List<String>>` (`() -> new ArrayList<>()`), and `StringBuilder::new` can satisfy `Function<String,StringBuilder>` (`s -> new StringBuilder(s)`) — the constructor chosen by overload resolution depends on the target's parameter list. **Array-constructor variant** — `int[]::new` (or `String[]::new`) is a special constructor reference that creates an array of a given length: equivalent to `n -> new int[n]`, satisfying `IntFunction<int[]>`. It is heavily used with `Stream.toArray(String[]::new)`. ## Why the distinction matters The key confusion is between **bound** (form 2) and **unbound** (form 3) — both look like `something::method`. The rule: if the part before `::` is an **object/expression**, the receiver is bound (captured). If it is a **type name** and the abstract method's first parameter matches the type, the receiver is unbound (passed in). The compiler decides which reading is legal against the target functional interface. All four kinds compile to an instance of the target functional interface — semantically identical to the equivalent lambda; the choice is purely about clarity.

  • Is a method reference ever more powerful than a lambda?
    No. It is strictly a shorthand for a lambda that makes a single call. Anything a method reference does, an equivalent lambda can express; the reverse is not true (lambdas can add logic, reorder args, etc.).
  • What functional interface does Math::max satisfy?
    Any two-arg interface matching its signature, e.g. IntBinaryOperator ((a,b)->Math.max(a,b)) or BinaryOperator<Integer> via boxing.

Think of a method reference as speed-dial. Static and constructor are dialing a fixed number. A bound reference is a contact saved to one specific person. An unbound reference is a template where you fill in 'who to call' (the receiver) at the moment you dial.

saying these in an interview costs you the question

  • Saying a method reference 'is a method' — it is an expression that produces a functional-interface instance.
  • Claiming method references are faster or fundamentally different from lambdas — they are equivalent, chosen for readability.
  • Confusing bound and unbound: thinking ClassName::method always means a static call.

context

open as a page

Explain the difference between a bound and an unbound instance-method reference, including how the receiver is determined in each.

level: middleimportance: must knowfreq 68%

basics

~20 s

In a bound reference (object::method) the object the method runs on is fixed when you write it. In an unbound reference (Class::method) that object is not fixed — it's passed in as the first argument each time the function is called.

open as a page

How do constructor references (ClassName::new) and array-constructor references (int[]::new) work, and which functional interfaces do they satisfy?

level: middleimportance: should knowfreq 55%

basics

~20 s

ClassName::new is shorthand for a lambda that calls a constructor — which constructor is picked depends on the target interface's parameters. int[]::new is a special form that creates an array of a given length, like n -> new int[n].

open as a page

How does the compiler resolve a method reference against a target functional interface, including overload disambiguation and when it fails?

level: seniorimportance: should knowfreq 42%

basics

~20 s

The compiler looks at the functional interface the reference must satisfy, then finds a method (or constructor) whose signature is compatible — possibly treating the first parameter as the receiver. If several methods fit equally, or none do, it's a compile error.

open as a page

When should you choose a method reference over an explicit lambda, and when does a lambda read better or behave differently?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Use a method reference when the lambda would do nothing but call one existing method with the same arguments. Use a lambda when you need extra logic, to reorder or transform arguments, or when the reference would be ambiguous or unclear.

open as a page