Method References
A method reference, written with the :: operator, is a compact shorthand for a lambda whose only job is to call one existing method — turning s -> obj.print(s) into obj::print .
Learn Method References in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You should be comfortable with lambda expressions and the basics of the Stream API . Method references have been available since Java 8 .
💡 Analogy: A lambda like s -> System.out.println(s) is you describing, step by step, "take the thing and print it." A method reference is simply pointing at the tool that already does that: System.out::println — "use that printer." When a method to do the job already exists, you don't re-explain it; you just name it.
Method references are not a new capability — every one is exactly equivalent to a lambda. They're a readability feature: shorter to write and, when used well, clearer to read.
If a lambda's body is just one method call that forwards its arguments, swap it for a reference. n -> System.out.println(n) becomes System.out::println ; s -> Integer.parseInt(s) becomes Integer::parseInt . Same behaviour, less noise.
There are exactly four forms. The trick to telling them apart is asking where the receiver object comes from .
This is where references shine. .map(Person::name) , .map(String::toUpperCase) , Comparator.comparingInt(Person::age) , and Collectors.toCollection(ArrayList::new) all read as a clean list of operations rather than a pile of tiny lambdas.
Use a reference when the lambda is a pure pass-through to one method ( s -> Main.shout(s) → Main::shout ). Keep a lambda the moment you reorder arguments, add a constant, or call more than one method — a reference can't express that, and forcing it hurts clarity.
Predict the result before opening each answer.
Answer: Type::staticMethod. max is a static method of Math , so it's a static-method reference equivalent to (a, b) -> Math.max(a, b) .
Answer: No. It adds a constant prefix — that's logic beyond a single existing method call, so it must stay a lambda (or you'd write "X"::concat only if the prefix were fixed and concat fit, which it does here as a bound reference). Keep it as a lambda for clarity.
Answer: 5 . String::length is unbound: the argument "hello" becomes the receiver, so it returns "hello".length() .
🎯 Your Turn — Trim and upper-case
Chain two unbound ( Type::instanceMethod ) references in a stream — no lambdas.
🧩 Mini-Challenge — A title extractor
Build a Function<Book, String> from the unbound reference Book::title and use it.
You can now read and write all four kinds of method reference — Type::staticMethod , obj::instanceMethod , Type::instanceMethod , and Type::new — use them throughout stream pipelines, and judge when a lambda is the better choice.
Next up: Built-in Functional Interfaces — the Function , Predicate , Consumer , and Supplier types your references plug into.
Practice quiz
What is a method reference?
- A pointer to memory
- A compact shorthand for a lambda that just calls one method
- A way to override a method
- A reflection API call
Answer: A compact shorthand for a lambda that just calls one method. A method reference (Type::method) is shorthand for a lambda whose body is a single method call.
Which operator forms a method reference?
- .
- ->
- ::
- =>
Answer: ::. Method references use the double-colon :: between the type/object and the method name.
Integer::parseInt is which kind of reference?
- object::instanceMethod
- Type::staticMethod
- Type::instanceMethod
- Type::new
Answer: Type::staticMethod. parseInt is static, so Integer::parseInt is a reference to a static method.
System.out::println is which kind?
- Type::staticMethod
- object::instanceMethod (bound)
- Type::instanceMethod (unbound)
- Type::new
Answer: object::instanceMethod (bound). It calls println on the specific object System.out, so it is a bound instance-method reference.
String::length is which kind?
- Type::staticMethod
- object::instanceMethod
- Type::instanceMethod (the first arg is the receiver)
- Type::new
Answer: Type::instanceMethod (the first arg is the receiver). String::length is unbound: the receiver is supplied as the first argument at call time.
ArrayList::new is which kind?
- Type::new (constructor reference)
- Type::staticMethod
- object::instanceMethod
- Type::instanceMethod
Answer: Type::new (constructor reference). ::new is a constructor reference, creating a new instance.
When can you replace a lambda with a method reference?
- Always
- When the lambda body is just a single call to an existing method with matching arguments
- Never in streams
- Only for static methods
Answer: When the lambda body is just a single call to an existing method with matching arguments. If the lambda simply forwards its arguments to one method, a method reference is the cleaner equivalent.
What is the difference between obj::m and Type::m for an instance method?
- None
- obj::m is bound to that object; Type::m takes the receiver as the first argument
- Type::m is faster
- obj::m is static
Answer: obj::m is bound to that object; Type::m takes the receiver as the first argument. A bound reference fixes the receiver; an unbound one expects the receiver as the first parameter.
Is s -> s.toUpperCase() equivalent to String::toUpperCase?
- Yes
- No
- Only for static
- Only in forEach
Answer: Yes. Both turn one String argument into its upper-cased form; String::toUpperCase is the unbound form.
Why prefer method references over lambdas where possible?
- They run on the GPU
- They are shorter and often read more clearly as intent
- They avoid exceptions
- They are required by streams
Answer: They are shorter and often read more clearly as intent. When applicable, a method reference is more concise and states 'apply this method' directly.