Search code examples
javalambdadoubleunary-operator

Local variable in enclosing scope with different results


Comparing two Operator types used for adding a double to a double with: DoubleUnaryOperator and UnaryOperator<Double>:

    public void test() {
        double doub = 10.0;

        // This is OK
        DoubleUnaryOperator oo = d -> {
            return doub + d;
        };          
        // Compilation error: Local variable doub defined in an enclosing scope must be final or effectively final
        UnaryOperator<Double> o = d -> {
            return doub + d; 
        };

        doub = oo.applyAsDouble(.3);
        doub = o.apply(.3);
    }  

Why is there a compilation error (doub is not final) only for the UnaryOperator<Double> ? Why are there different results if the variable declaration never changes?


Solution

  • In my case (Java12) I got error in both DoubleUnaryOperator and UnaryOperator.

    The case in your situation is that you are reassigning the doub with oo function result and after that you are trying to use the doub in next operator.

    I'm citing the: Difference between final and effectively final

    Informally, a local variable is effectively final if its initial value is never changed -- in other words, declaring it final would not cause a compilation failure.

    So, what I understood after checks is:

    If the variable is final then it can be always used in the lambda expressions because there is no possibility to reassign it (there is - reflections, but that's another topic).

    The effectively final variable appears when the declared variable remains unchanged.

    If you would assign the result of oo to newly declared variable then you should be able to use this variable in o.

    I believe that you tried to achieve 10.6 value, here's the sample:

    double doub = 10.0;
    DoubleUnaryOperator oo = d -> {
        return doub + d;
    };
    double ahh = oo.applyAsDouble(.3);
    UnaryOperator<Double> o = d -> {
        return ahh + d;
    };
    System.out.println(o.apply(.3)); //The o.apply(.3) can be assigned to new variable 
    

    Any reassigning to doub or ahh results in compile error (Java11)