Why do lambdas in Java 8 disallow forward reference to member variables where anonymous classes don't?

前端 未结 1 1190
温柔的废话
温柔的废话 2020-12-14 02:26

The following class contains a member variable runnable which is initialized with an instance of an anonymous inner class. The inner class references the same m

相关标签:
1条回答
  • 2020-12-14 02:27

    Bug #JDK-8027941 describes exactly this. Dan Smith (Project Lambda Specification Lead) writes that it's not a bug, and not limited to lambdas.

    In the comments on a related bug report, he puts it like this:

    8.3.2.3: First, a "use" of a field in a field initializer is generally prohibited if the use occurs before the field declaration. The spec is not very clear on this, but the intent has always been that "before" includes the field's own initializer. So "int x = x+1;" is not a valid field declaration.

    He also remarks:

    It would possible to add a feature that would treat lambda bodies specially, like bodies of anonymous classes (or, more generally, allow a lambda to refer to itself if it is a variable initializer), but this has not been done. (FWIW, a straightforward tweak of 8.3.2.3 would not be entirely safe, just like the 4th bullet is not currently entirely safe: "Function f = (Function) ((Function) e -> f.apply(e)).apply(null);".)

    I think the problem is that the designers of Java want to have simple, syntactic rules to decide what kind of statements are allowed, rather than depending on more complex, semantic code analysis. The benefit is probably a simpler spec and therefore less requirements on compilers, while the cost is that programmers can't express every program -- at least not in the way they want to.


    As Marko Topolnik points out, there is a solution: fully qualify the field. Example from the bug report:

    import java.util.function.Function; 
    
    public class LambdaSelfRef { 
    
        // COMPILATION FAILURE 
        public static Function<Object, Object> op1 = e -> op1.apply(e); 
    
        // COMPILES OK 
        public static Function<Object, Object> op2 = e -> LambdaSelfRef.op2.apply(e); 
    
        /* ... */
    }
    
    0 讨论(0)
提交回复
热议问题