Search code examples
javamultithreadinglambdajava-8runnable

Different behavior of lambdas for Runnables created


Below are two sets of codes for creating multiple runnable objects via Java 8 lambdas. However, I am seeing a difference in the behavior of object creation.

Code 1 - create multiple objects, as hashcode is different

PasswordUtils passwordUtils = new PasswordUtils();
for(int i = 0 ; i < 100 ; i++) {
    Runnable r = () -> passwordUtils.print();            //difference       
    System.out.println(r.hashCode());
}

Output -

1129670968
1023714065
.. //varies in each iteration

Code 2 - create single object, as hashcode is same for all object.

for(int i = 0 ; i < 100 ; i++) {
    Runnable r = () -> new PasswordUtils().print();      //difference       
    System.out.println(r.hashCode());
}

Output-

1254526270
1254526270
... // same on all iterations

The difference is when the PasswordUtils object is created. What is the reason for this difference?

Edit: Just to complete the code, one can use

class PasswordUtils {
    void print() {
    }
}

Solution

  • Based on the comment from Does a lambda expression create an object on the heap every time it's executed?

    ... For stateless lambdas (those that do not capture anything from their lexical context), only one instance will ever be created (lazily), and cached at the capture site. (This is how the implementation works; the spec was carefully written to allow, but not require, this approach.)

    In code one a PasswordUtil is created and then used in the lambda, so it does capture something from the lexical context. In code 2, the PasswordUtil is created inside of the lambda, and the lambda never captures anything from it's context at creation, so only one instance is created. Hence the same hashCode is output.

    The answer to the linked question provides more information about where this criteria can be found in the JLS. I've added an answer here to show why this specific case is example of when a new instance is not being created.