1

This question already has an answer here:

But I read a post(Why Do Local Variables Used in Lambdas Have to Be Final or Effectively Final?). It posts an example:

Supplier<Integer> incrementer(int start) {
  return () -> start++;
}

The code will cast compile-error. The post tries to explain the reason and say:

The basic reason this won't compile is that the lambda is capturing the value of start, meaning making a copy of it. Forcing the variable to be final avoids giving the impression that incrementing start inside the lambda could actually modify the start method parameter. But, why does it make a copy? Well, notice that we are returning the lambda from our method. Thus, the lambda won't get run until after the start method parameter gets garbage collected. Java has to make a copy of start in order for this lambda to live outside of this method.

I cannot understand its explanation and I have two questions:

  1. What does "the lambda won't get run until after the start method parameter gets garbage collected" mean?
  2. Why does it make a copy?
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
huangjs
  • 459
  • 1
  • 5
  • 13
  • When you don’t understand that explanation, why don’t you just ignore it and use one of the three Q&A that you acknowledge to answer your question? – Holger Oct 24 '19 at 08:17

2 Answers2

3
  1. It means that the lambda code (the start++ part) doesn't get executed until the Supplier object's get() method is called, which happens somewhere in the caller of the incrementer() method, i.e. some time after the incrementer() method has returned.

    Whoever wrote that is badly mistaken, because parameters are on the stack, not the heap, so they do not get "garbage collected". Given a huge mistake like that, I recommend you ignore that post, because the writer doesn't know what (s)he's taking about.

  2. That is already covered in the accepted answer of the first link you provided. I suggest you read it.

Andreas
  • 154,647
  • 11
  • 152
  • 247
1

When you return from a function, variables and objects declared inside a function that are not "returned" become "out of scope" and should not be reached by the programmer anymore, in the case of java, such objects are eventually deleted by the garbage collector.

public String enterNewScope(String a, String b) {
    String c = a + b;
    String d = b + c;
    String e = c + d;

    return d;
}

public static void main(String...args) {
    //The variables a, b, c, and e are now out of scope
    //d is returned by the function so it's still in use.
    String dReturned = enterNewScope("hello", "world");
}

The function Supplier<Integer> incrementer(int start) {...} returns a lambda, but you can only use the lambda after the function has already returned, meaning whenever you are capable of using that lambda, the variable 'start' is out of scope. So Java will make a copy of your 'start' variable just in case that it cannot be reached when you call your lambda.

Check out this other answer for more details: Lambda Expression and Variable Capture

ABOODYFJ
  • 30
  • 1
  • 9
  • 1
    would be more accurate to say the variable 'start' is out of scope. the start variable might or might not be in memory, it can't really be known. maybe emphasize that in java lambdas close over values, not over variables. – Nathan Hughes Oct 23 '19 at 17:44
  • @NathanHughes good point, edited the answer to try and make it clear for op. – ABOODYFJ Oct 23 '19 at 18:18