Outer local variable capture works basically identically in Java 1.1 
lambdas and Java 8 lambdas. It is inaccurate to say that 1.1 lambdas 
capture values and 8 lambdas capture variables. Java 8 doesn't require you 
to explicitly write "final" on captured variables like previous versions of 
Java, but they must be effectively final, which means you can change the 
contents, but you can't change the top-level variable reference or in the 
case of a primitive, you can't change the value after assignment.

The C# 5 change is somewhat controversial. It guards against an extremely 
common programmer error in C# <5 (and JavaScript), but it's a breaking 
change that breaks code that depends on existing behavior and it's 
lexically inconsistent. "for" loops and "foreach" loops will have 
inconsistent semantics in this regard. See:
http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

BTW, I tested my assertion:

    public static void lambdaTest() {
        // Pre Java 8, captured variables had to be explicitly declared 
final. In Java 8, they only need to be "effectively final".
        List<String> l = new ArrayList<>();

        Runnable lambda11 = new Runnable() {
            @Override
            public void run() {
                System.out.println("lambda11: l.size() = " + l.size());
            }
        };
        Runnable lambda8 = () -> System.out.println("lambda8: l.size() = " 
+ l.size());

        System.out.println("Done creating lambda expressions. l.size() = " 
+ l.size());

        lambda11.run();
        lambda8.run();

        // Reassignment would violate the "effectively final" requirement 
of a captured variable.
        //l = new ArrayList<>();
        l.add("test");

        System.out.println("Added test value. l.size() = " + l.size());

        lambda11.run();
        lambda8.run();
    }

On Wednesday, March 13, 2013 12:45:12 PM UTC-5, Casper Bang wrote:
>
>
> Casper, Java 8 lambdas are completely backwards compatible with Java 1.1 
>> style lambda APIs. I don't see what else they could do without breaking 
>> backward compatibility. The final requirement on outer variable capture is 
>> there on purpose because it prevents a lot of common mistakes like this: 
>> http://blog.roboblob.com/2012/09/30/dot-net-gotcha-nr2-loop-variables-and-closures/
>>
>
> Yeah I guess there's enough reflection code, relying on classpath 
> discovery (even if an SPI approach is so much cleaner) that it would cause 
> trouble - even for a compile target 1.8.
>
> While I have often been annoyed at the hoist-to-heap tricks you have to go 
> through in Java to close over a variable rather than a (copy of a) value, 
> it makes sense for there to be two distinct mechanisms (close over value 
> with Java 1.1 lambda's, close over variables with Java 1.8 lambdas). 
> Ironically, C# went the other way and just recently added "close over 
> value" support for the foreach idiom in 5.0.
>

-- 
You received this message because you are subscribed to the Google Groups "Java 
Posse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/javaposse?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to