Let me offer some perspective on why we added this feature to the language, when clearly we didn't strictly need to (all methods refs can be expressed as lambdas).

Note that there isn't any right answer. Anyone who says "always use a method ref instead of a lambda" or "always use a lambda instead of a method ref" should be ignored.

This question is very similar in spirit to "when should I use a named class vs an anonymous class"? And the answer is the same: when you find it more readable. There are certainly cases that are definitely one or definitely the other, but there's a host of grey in the middle, and judgment must be used.

The theory behind method refs is simple: names matter. If a method has a name, then referring to it by name, rather than by an imperative bag of code that ultimately just turns around and invokes it, is often (but not always!) more clear and readable.

The arguments about performance or about counting characters are mostly red herrings, and you should ignore them. The goal is writing code that is crystal clear what it does. Very often (but not always!) method refs win on this metric, so we included them as an option, to be used in those cases.

A key consideration about whether method refs clarify or obfuscate intent is whether it is obvious from context what is the shape of the function being represented. In some cases (e.g., map(Person::getLastName), it's quite clear from the context that a function that maps one thing to another is required, and in cases like this, method references shine. In others, using a method ref requires the reader to wonder about what kind of function is being described; this is a warning sign that a lambda might be more readable, even if it is longer.

Finally, what we've found is that most people at first steer away from method refs because they feel even newer and weirder than lambdas, and so initially find them "less readable", but over time, when they get used to the syntax, generally change their behavior and gravitate towards method references when they can. So be aware that your own subjective initial "less readable" reaction almost certainly entails some aspect of familiarity bias, and you should give yourself a chance to get comfortable with both before rendering a stylistic opinion.

Answer from Brian Goetz on Stack Overflow
Top answer
1 of 6
308

Let me offer some perspective on why we added this feature to the language, when clearly we didn't strictly need to (all methods refs can be expressed as lambdas).

Note that there isn't any right answer. Anyone who says "always use a method ref instead of a lambda" or "always use a lambda instead of a method ref" should be ignored.

This question is very similar in spirit to "when should I use a named class vs an anonymous class"? And the answer is the same: when you find it more readable. There are certainly cases that are definitely one or definitely the other, but there's a host of grey in the middle, and judgment must be used.

The theory behind method refs is simple: names matter. If a method has a name, then referring to it by name, rather than by an imperative bag of code that ultimately just turns around and invokes it, is often (but not always!) more clear and readable.

The arguments about performance or about counting characters are mostly red herrings, and you should ignore them. The goal is writing code that is crystal clear what it does. Very often (but not always!) method refs win on this metric, so we included them as an option, to be used in those cases.

A key consideration about whether method refs clarify or obfuscate intent is whether it is obvious from context what is the shape of the function being represented. In some cases (e.g., map(Person::getLastName), it's quite clear from the context that a function that maps one thing to another is required, and in cases like this, method references shine. In others, using a method ref requires the reader to wonder about what kind of function is being described; this is a warning sign that a lambda might be more readable, even if it is longer.

Finally, what we've found is that most people at first steer away from method refs because they feel even newer and weirder than lambdas, and so initially find them "less readable", but over time, when they get used to the syntax, generally change their behavior and gravitate towards method references when they can. So be aware that your own subjective initial "less readable" reaction almost certainly entails some aspect of familiarity bias, and you should give yourself a chance to get comfortable with both before rendering a stylistic opinion.

2 of 6
19

Long lambda expressions consisting of several statements may reduce the readability of your code. In such a case, extracting those statements in a method and referencing it may be a better choice.

The other reason may be re-usability. Instead of copy&pasting your lambda expression of few statements, you can construct a method and call it from different places of your code.

🌐
Oracle
docs.oracle.com › javase › tutorial › java › javaOO › methodreferences.html
Method References (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases. You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method.
🌐
Reddit
reddit.com › r/java › subtle difference between lambda and method reference
r/java on Reddit: Subtle difference between lambda and method reference
September 23, 2022 -

So. Turns out there's a subtle difference between lambdas and method references. For instance, compare: myInstance::getStuff and () -> myInstance.getStuff()

This will mostly be considered equivalent. But. If myInstance happens to be null, the lambda will throw a null pointer when the lambda gets evaluated, but the method reference will throw right away when trying to access the reference.

So what? Well. This IS important if the code evaluating the lambda is inside a null-pointer try-catch.

Say I have a function mightBeNull(Supplier<T> function) that does something along the lines of:

try {
    doStuff(function.get().getSomeMore().getSomeMore());
} catch (NullPointerException e) {
    doOtherStuff();
}

If so. The call: mightBeNull(() -> myNullVariable.getStuff()) will work without exceptions, but the "equivalent": mightBeNull(myNullVariable::getStuff) will throw a null pointer exception right att the function call.

Top answer
1 of 3
20

In many scenarios, I think lambda and method-reference is equivalent. But the lambda will wrap the invocation target by the declaring interface type.

For example

public class InvokeTest {

    private static void invoke(final Runnable r) {
        r.run();
    }

    private static void target() {
        new Exception().printStackTrace();
    }

    @Test
    public void lambda() throws Exception {
        invoke(() -> target());
    }

    @Test
    public void methodReference() throws Exception {
        invoke(InvokeTest::target);
    }
}

You will see the console output the stacktrace.

In lambda(), the method calling target() is lambda$lambda$0(InvokeTest.java:20), which has traceable line info. Obviously, that is the lambda you write, the compiler generates an anonymous method for you. And then, the caller of the of the lambda method is something like InvokeTest$$Lambda$2/1617791695.run(Unknown Source), that is the invokedynamic call in JVM, it means the call is linked to the generated method.

In methodReference(), the method calling target() is directly the InvokeTest$$Lambda$1/758529971.run(Unknown Source), it means the call is directly linked to the InvokeTest::target method.

Conclusion

Above all, compare to method-reference, using lambda expression will only cause one more method call to the generating method from lambda.

2 of 3
38

It's all about the metafactory

First, most method references do not need desugaring by the lambda metafactory, they are simply used as the reference method. Under the section "Lambda body sugaring" of the Translation of Lambda Expressions ("TLE") article:

All things being equal, private methods are preferable to nonprivate, static methods preferable to instance methods, it is best if lambda bodies are desugared into in the innermost class in which the lambda expression appears, signatures should match the body signature of the lambda, extra arguments should be prepended on the front of the argument list for captured values, and would not desugar method references at all. However, there are exception cases where we may have to deviate from this baseline strategy.

This is further highlighted further down in TLE's "The Lambda Metafactory":

metaFactory(MethodHandles.Lookup caller, // provided by VM
            String invokedName,          // provided by VM
            MethodType invokedType,      // provided by VM
            MethodHandle descriptor,     // lambda descriptor
            MethodHandle impl)           // lambda body

The impl argument identifies the lambda method, either a desugared lambda body or the method named in a method reference.

A static (Integer::sum) or unbounded instance method (Integer::intValue) references are the 'simplest' or the most 'convenient', in the sense that they can be optimally handled by a 'fast-path' metafactory variant without the desugaring. This advantage is helpfully pointed out in TLE's "Metafactory variants":

By eliminating arguments where they are not needed, classfiles become smaller. And the fast path option lowers the bar for the VM to intrinsify the lambda conversion operation, enabling it to be treated as a "boxing" operation and faciliating unbox optimizations.

Naturally, an instance-capturing method reference (obj::myMethod) needs to provide the bounded instance as an argument to the method handle for invocation, which may mean the need of desugaring using 'bridge' methods.

Conclusion

I'm not exactly sure what is the lambda 'wrapper' you are hinting at, but even though the ultimate result of using your user-defined lambdas or method references are the same, the way that is reached seems to be quite different, and can be different in the future if that's not the case now. Hence, I suppose it's more likely than not that method references can be handled in a more optimal way by the metafactory.

🌐
Baeldung
baeldung.com › home › java › core java › method references in java
Method References in Java | Baeldung
March 26, 2025 - As we’ve seen so far, method references are a great way to make our code and intentions very clear and readable. However, we can’t use them to replace all kinds of lambda expressions since they have some limitations.
🌐
TutorialsPoint
tutorialspoint.com › differences-between-lambda-expression-and-method-reference-in-java
Differences between Lambda Expression and Method Reference in Java?
The arrow (->) operator can be used to connect the argument and functionality in a lambda expression while the (::) operator separates the method name from the name of an object or class in a method reference. ... import java.util.*; public class LambdaMethodReferenceTest { public static void ...
🌐
Coderanch
coderanch.com › t › 704526 › java › Difference-Lambda-method-reference
Difference between Lambda and method reference? (Features new in Java 8 forum at Coderanch)
There is one difference, but it's not easy to see. The lambda is just that - a lambda. The method reference on the other hand is a closure - it captures the current value of System.out. If you would make the lambda / method reference serializable (by casting it to Consumer<Integer> & Serializable), ...
Find elsewhere
🌐
Foojay
foojay.io › home › method reference vs lambda java challenge
Method Reference VS Lambda Java Challenge | foojay
August 23, 2021 - In Java, the “Function” functional interface can be used as a first-class citizen function, meaning that we can pass a function to a method and declare it as a variable, giving the developer a lot of power. And now it’s time for you now to test your abilities with lambdas and functional interfaces!
🌐
DZone
dzone.com › coding › languages › java lambda: method reference
Java Lambda: Method Reference
October 11, 2018 - Thus, a lambda expression results in a form of anonymous class. Method reference is an important feature related to lambda expressions, which can let you reuse existing method definitions and pass them just like lambda expressions.
🌐
GeeksforGeeks
geeksforgeeks.org › java › java-method-references
Java Method References - GeeksforGeeks
2 weeks ago - Method references use the double colon (::) operator and are mainly used with functional interfaces. Introduced in Java 8 as an alternative to lambda expressions
🌐
Medium
medium.com › @edouard.kaiser › lambda-and-method-reference-133867e19c01
Lambda and method reference. Java 8 brought us the lambda… | by Edouard Kaiser | Medium
February 26, 2018 - The most important thing they don’t say is that, if the referenced method is the instance method of an arbitrary object of a particular type, the object (the receiver of the method) is considered to be the first argument in the functional interface used. ... The java.util.function.Function<String,String> means the lambda expression has to respect the signature:
🌐
Medium
medium.com › codimis › what-is-method-reference-and-why-is-it-used-in-place-of-lambda-expressions-2a97fe01b07b
What is Method Reference and Why is It Used in Place of Lambda Expressions? | by Büşra Bozgöz | Codimis | Medium
March 22, 2024 - To briefly describe method references, we need to say that method references are a concise and more readable way of writing lambda expressions, but there are only particular use cases in which we can use them.
🌐
Medium
medium.com › @Zimmendra › understanding-java-lambda-expressions-and-method-references-f59ce7f0c2b0
Understanding Java Lambda Expressions and Method References | by Heshanth Zimmendra | Medium
November 19, 2024 - Lambda expressions and method ... maintainability of code. While lambda expressions are ideal for defining custom logic, method references provide a cleaner way to refer to existing methods....
🌐
DZone
dzone.com › coding › java › java lambda expressions vs method references
Java Lambda Expressions vs Method References
April 9, 2013 - In summary, there are circumstances in which we would like to use some preexisting code as the implementation for a functional interface, in those case we could use one of several variants of method references instead of a more verbose lambda expression.
Top answer
1 of 2
4

There is no way “to transform any lambda expression to method reference”, but you can implement a factory for a particular target type, if this serves recurring needs:

public static <A,B> Predicate<A> bind2nd(BiPredicate<A,B> p, B b) {
    return a -> p.test(a, b);
}

with this, you can write

words.stream().filter(bind2nd(String::endsWith, ".")).forEach(System.out::println);

but actually, there’s no advantage. Technically, a lambda expression does exactly what you want, there’s the minimum necessary argument transformation code, expressed as the lambda expression’s body, compiled into a synthetic method and a method reference to that synthetic code. The syntax
s -> s.endsWith(".") also is already the smallest syntax possible to express that intent. I doubt that you can find a smaller construct that would still be compatible with the rest of the Java programming language.

2 of 2
3

You can use selectWith() from Eclipse Collections. selectWith() takes a Predicate2 which takes 2 parameters instead of a Predicate. The second parameter to selectWith() gets passed as the second parameter to the Predicate2 every time it's called, once per item in the iterable.

MutableList<String> words = Lists.mutable.with("toto.", "titi.", "other");
words.selectWith(String::endsWith, ".").each(System.out::println);

By default Eclipse Collections is eager, if you want to iterate lazily then you can use asLazy()

words.asLazy().selectWith(String::endsWith, ".").each(System.out::println);

If you can't change from List:

List<String> words = Arrays.asList("toto.", "titi.", "other");
ListAdapter.adapt(words).selectWith(String::endsWith, ".").each(System.out::println);

Eclipse Collections' RichIterable has several other *With methods which work well with method references, including rejectWith(), partitionWith(), detechWith(), anySatisfyWith(), allSatisfyWith(), noneSatisfyWith(), collectWith()

Note: I am a contributor to Eclipse Collections.

🌐
JetBrains
jetbrains.com › help › inspectopedia › Convert2MethodRef.html
Lambda can be replaced with method reference | Inspectopedia Documentation
March 4, 2026 - While often it could be a matter of taste, method references are more clear and readable compared to lambdas. ... Can be used to locate inspection in e.g. Qodana configuration files, where you can quickly enable or disable it, or adjust its settings.
🌐
Dirask
dirask.com › posts › Java-8-difference-between-lambda-expression-and-method-reference-jMqXdj
Java 8 - difference between lambda expression and method reference
In this example, we use both lambda expression and method reference to achieve the same effect - print list items in lowercase. import java.io.*; import java.util.ArrayList; import java.util.List; public class Example { public static void main(String[] args) throws IOException { List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); // Using lambda expression to print list items in lower case System.out.println("----- Lambda expression -----"); list.stream().map(x -> x.toLowerCase()) .forEach(x -> System.out.println(x)); // Using method reference to print list items in lower case System.out.println("----- Method reference -----"); list.stream().map(String::toLowerCase).sorted() .forEach(System.out::println); } }
🌐
Dev.java
dev.java › learn › writing-lambda-expressions-as-method-references
Writing Lambda Expressions as Method References
October 26, 2021 - Defining your own classes, declaring member variables, methods, and constructors. ... How to model your immutable data with records to make your code simpler and more readable. ... Understanding numbers, characters and strings of characters. ... Leveraging inheritance in Java applications. ... Creating and using interfaces. ... Working with parameterized types. ... Using Lambda ...
🌐
Medium
medium.com › @damian.kolasa › performance-implications-of-lambdas-and-method-references-when-mapping-a-stream-in-java-79f6e2da6806
Performance implications of lambdas and method references when mapping a stream in Java | by Damian Kolasa | Medium
June 13, 2018 - After all before lambda expressions came to Java language that’s exactly what we all did. Cached anonymous inner class. Second category represents lambda expressions that are not self-contained nor are pure functions. Those are the lambda expressions that require reference to external world to perform their logic.