Path: csiph.com!aioe.org!eternal-september.org!feeder.eternal-september.org!mx04.eternal-september.org!.POSTED!not-for-mail From: Steven Simpson Newsgroups: comp.lang.java.programmer Subject: Re: Why is that in JDK8: value used in lambda expression shuld be effectively final? Date: Wed, 02 Jan 2013 14:15:18 +0000 Organization: A noiseless patient Spider Lines: 64 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Injection-Info: mx04.eternal-september.org; posting-host="0d771e3708e29ef01409ed69429633ae"; logging-data="13214"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/3A+8xys6YL5BDjrRInqahQRbuQWnIa/M=" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/17.0 Thunderbird/17.0 In-Reply-To: Cancel-Lock: sha1:zHxGmhpV3V7bqOg7/i8Lbl0yK/U= Xref: csiph.com comp.lang.java.programmer:20870 On 02/01/13 12:51, jeti789@web.de wrote: > I'm currently plaing with JDK8 and using lambda-8-b69-windows-i586-17_dec_2012. I wonder why this does not compile: > > List ints = new ArrayList<>(); > ints.add(1); > ints.add(2); > ints.add(3); > > int sum = 0; > ints.forEach(i -> {sum += i;}); > > The compiler error is "value used in lambda expression shuld be effectively final" It's the same reason why inner classes can't mutate local variables in the enclosing scope. The method that accepts the lambda or inner class instance cannot formally make any guarantee not to invoke the supplied code in a non-serial way. forEach could informally specify that it will execute its argument only on its calling thread, and not after it returns, but the compiler could not detect that guarantee and allow 'sum' to be modified. (I'm using 'formal' to indicate something that can be detected by the compiler.) > However, this here compiles: > > int sumArray[] = new int[] { 0 }; > ints.forEach(i -> {sumArray[0] += i;}); Ultimately, the compiler can't stop anyone from shooting themselves in the foot. You can still access an instance variable unsafely via a lambda, for example. Stopping the protection at the level of local variables could seem a bit arbitrary, but it is still useful, since you expect the use of local variables to be intrinsically thread-safe (and they remain so under this level of protection), and trying to provide more comprehensive protection would be increasingly difficult. > I'm a bit confused now. Does this mean that JDK8 closures are no true closures or is this a bug in my IDE (IDEA 12)? For some definition of closures (one including mutable local capture), JDK8 lambdas are not closures (hence, they are not called closures). AIUI, the main goal of lambdas was to reduce verbosity/overhead of anonymous classes used with algorithms that better exploit parallelism. These do not typically require or work well with shared variables, and supporting mutable locals efficiently would require considerable extra effort for something substantially beyond the main goal. I'm sure you can get a more authoritative explanation by checking the lambda mailing-list archives: I suggest looking for terms such as 'mutable local capture', and 'effectively final'. -- ss at comp dot lancs dot ac dot uk