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.

Answer from JasonMing on Stack Exchange
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.

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.

Discussions

Using lambda and method reference differ significantly in performance with Java 8 streams - Support - Kotlin Discussions
I have found that when working with Java 8 streams, using lambda and method reference can differ significantly in performance. Here is the code to invert an array of 1 GB executed both sequentially and in parallel: inl… More on discuss.kotlinlang.org
🌐 discuss.kotlinlang.org
2
September 27, 2020
lambda x method reference taste
I always do method references if possible. The benefit is that it is immediately clear that the call is to a method with only 1 parameter and the argument is an element of the collection that is streamed over. It's not necessarily the case with a lambda. Method references leave less room for errors or oversights, such as negation. You also don't have to invent intermediate variable names. More on reddit.com
🌐 r/java
35
18
January 21, 2022
Subtle difference between lambda and method reference
It is a subtle difference, yes. However, IMHO: catching a NPE is not something you should ever do. It is always a programmer error that needs to be fixed at its root cause. Catching it just allows for bad code, and code protected with such a catch then tends to go from bad to worse over time. More on reddit.com
🌐 r/java
42
74
September 23, 2022
When do you draw a line on lambda vs ecs container?
Expected runtime More on reddit.com
🌐 r/aws
53
53
July 7, 2023
🌐
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.

🌐
Kotlin Discussions
discuss.kotlinlang.org › support
Using lambda and method reference differ significantly in performance with Java 8 streams - Support - Kotlin Discussions
September 27, 2020 - I have found that when working with Java 8 streams, using lambda and method reference can differ significantly in performance. Here is the code to invert an array of 1 GB executed both sequentially and in parallel: inl…
🌐
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 - Lambda expression and fine grained mapping. As you can see IDE suggests to replace them with a method reference. Or we can do a performance hack and remove one of the mapping functions:
🌐
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 - JIT Optimization: The Just-In-Time (JIT) compiler in modern JVMs optimizes lambdas as effectively as it does with traditional methods or anonymous classes. This means that lambdas can be just as fast in terms of execution. Overhead: If you use lambda expressions in performance-critical code, there might be a very slight overhead due to the creation of additional method handles or function objects at runtime.
🌐
GitHub
github.com › pcarfrey › java-performance-method-reference-vs-lambda
GitHub - pcarfrey/java-performance-method-reference-vs-lambda: Comparing performance of Java Method References vs Lambdas
Test: arrayListPrintln, Type: class java.lang.String, Number of Element: 10000 Lambda Estimated Time: 159724599 Method Reference Estimated Time: 146702949
Author   pcarfrey
Find elsewhere
🌐
Foojay
foojay.io › home › method reference vs lambda java challenge
Method Reference VS Lambda Java Challenge | foojay
August 23, 2021 - On the other hand, with method reference, the constructor will be invoked right away only where the method reference is assigned, not on the method invocation. ... With lambdas, every time the run method is invoked, the constructor will be invoked, ...
🌐
TutorialsPoint
tutorialspoint.com › differences-between-lambda-expression-and-method-reference-in-java
Differences between Lambda Expression and Method Reference in Java?
Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.
🌐
Reddit
reddit.com › r/java › lambda x method reference taste
r/java on Reddit: lambda x method reference taste
January 21, 2022 -

Hello guys, I'm jr web back-end and during my "trainee introduction" one of my seniors and my job's SonarQube forced me to switch lambda expressions for method reference. I've searched a bit about this change wondering if all of this is about performance, or patterns or code reduction but I didn't find something solid, I know it's probably has been discussed here, but I want more opinions about. For me, lambda expression is way better to read and code, please don't judge me :D

🌐
JavaTechOnline
javatechonline.com › home › method reference in java 8 [::]
Method Reference In Java 8 [::] - JavaTechOnline
July 10, 2025 - When we use lambda with Java 8 Streams, it provides better performance than the method reference.
🌐
DZone
dzone.com › coding › java › java lambda expressions vs method references
Java Lambda Expressions vs Method References
April 9, 2013 - Now we can use lambda expressions to implement functional interfaces as we have seen in previous posts, but the lambda expressions are not the only mechanism we can use for this purpose. Particularly where there are preexisting code that we would like to reuse we can simplify the implementation of the functional interface by using method references.
🌐
Oracle
oracle.com › technetwork › java › jvmls2013kuksen-2014088.pdf pdf
JDK 8: Lambda Performance study Sergey Kuksenko
Capture: lambda slow warmup · Main culprits: jsr292 LF implementation · layer of LF’s generated methods · HotSpot (interpreter) calling a method is hard (even simple delegating · methods) Slide 33/55. Capture: time-to-performance · extra invocations for anonymous ·
🌐
Ionutbalosin
ionutbalosin.com › 2018 › 12 › passing-thismethod-reference-within-a-loop-affects-performance
Passing this::method reference within a loop affects performance – Ionut Balosin
December 1, 2018 - As opposed to the previous flame graphs, in this case, there is no captured Lambda$51.get$Lambda call by the graph, hence there substantially fewer heap allocations. avoid passing this::method to a method within a loop since it really affects performance
🌐
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 - In some cases, we must return the object or void. We cannot do this using the method reference. Lambda expressions allow you to define your own parameters and perform a lot more logical processing each time.
🌐
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.
🌐
Medium
proandroiddev.com › kotlin-lambda-vs-method-reference-fdbd175f6845
Kotlin. Lambda vs Method Reference | by Gurgen Gevondov | ProAndroidDev
March 13, 2021 - That is, if we pass lambda to button constructor, the listener variable will be used after performing button click and it will already be initialized. And here is what will happen if we use method reference instead of lambda. In this case Function0 anonymous class is created as well but if ...
🌐
Medium
medium.com › @naeem0313 › kotlin-lambda-vs-method-reference-efe41718e72e
Kotlin. Lambda vs Method Reference | by Muhammad Naeem | Medium
May 18, 2023 - Understanding and debugging complex lambdas might require additional effort, and overly nested or convoluted lambdas can make the code harder to read and maintain. Method references provide a concise way to refer to an existing method as a value.
🌐
Jyro117
blog.jyro117.com › 2013 › 10 › java-8-method-reference-and-lambda.html
Jyro Developments: Java 8 Method Reference and Lambda Performance
Anyone familiar with Java will see the new syntax and be in awe at the performance. And of course here are the results: reflective invocation (without setAccessible) 4.847 ns reflective invocation (with setAccessible) 4.593 ns methodhandle invocation 11.511 ns static final methodhandle invocation 0.000 ns direct invocation 0.000 ns method reference invocation 0.000 ns lambda invocation 0.000 ns
🌐
Oracle
docs.oracle.com › javase › tutorial › java › javaOO › methodreferences.html
Method References (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it's often clearer to refer to the existing method by name.