Java 8 Method references called on a local variable

JLS 15.13.5 may hold the explanation:

The timing of method reference expression evaluation is more complex than that of lambda expressions (§15.27.4). When a method reference expression has an expression (rather than a type) preceding the :: separator, that subexpression is evaluated immediately. The result of evaluation is stored until the method of the corresponding functional interface type is invoked; at that point, the result is used as the target reference for the invocation. This means the expression preceding the :: separator is evaluated only when the program encounters the method reference expression, and is not re-evaluated on subsequent invocations on the functional interface type.

As I understand it, since in your case transformer is the expression preceding the :: separator, it is evaluated just once and stored. Since it doesn't have to be re-evaluated in order to invoke the referenced method, it doesn't matter that transformer is later assigned null.


Wild guess but to me, here is what happens...

The compiler cannot assert that the created stream is synchronous at all; it sees this as a possible scenario:

  • create stream from relationships argument;
  • reaffect transformer;
  • stream unrolls.

What is generated at compile time is a call site; it is linked only when the stream unrolls.

In your first lambda, you refer to a local variable, but this variable is not part of the call site.

In the second lambda, since you use a method reference, it means the generated call site will have to keep a reference to the method, therefore the class instance holding that method. The fact that it was referred by a local variable which you change afterwards does not matter.

My two cents...