I cannot reproduce your statement that one compiles while the other does not. For me, neither compiles.
Information:java: Errors occurred while compiling module 'tuts'
Information:javac 1.8.0_192 was used to compile java sources
Information:9/14/2019 8:10 PM - Build completed with 1 error and 0
warnings in 2 s 849 ms
C:\Users\Philip\Code\tuts\src\test\java\tuts\UnaryOperatorTest.java
Error:(13, 60) java: local variables referenced from a lambda
expression must be final or effectively final
The problem is that you are attempting to reassign to doub
in the outer scope after creating a new scope within the lambda that uses doub
.
The functionality of the lambda becomes non-deterministic if you can alter the value of doub
outside the scope of the lambda. Therefore, values from the outer scope must be declared final
or be 'effectively' final (meaning you follow the rules and don't attempt to reassign to them in the outer scope).
You can get both alternatives to work if you just assign the results to a different variable (result
, in the following example):
import org.junit.Assert;
import org.junit.Test;
import java.util.function.DoubleUnaryOperator;
import java.util.function.UnaryOperator;
public class UnaryOperatorTest {
@Test
public void testDoubleUnaryOperator() {
double doub = 10.0;
DoubleUnaryOperator doubleUnaryOperator = d -> d + doub;
double result = doubleUnaryOperator.applyAsDouble(0.3);
Assert.assertEquals(10.3, result, Double.MIN_VALUE);
}
@Test
public void testUnaryOperator() {
double doub = 10.0;
UnaryOperator<Double> unaryOperator = d -> d + doub;
double result = unaryOperator.apply(0.3);
Assert.assertEquals(10.3, result, Double.MIN_VALUE);
}
}
(Edit) I have copied and pasted your code verbatim. Neither FunctionalInterface
example compiles in Java 8, as you can see from the problematic line numbers (31 and 36):

However, making doub
effectively final by assigning to result
instead allows the code to compile:
