封闭范围内的局部变量具有不同的结果

比较用于将双精度数添加到双精度数的两个运算符类型:DoubleUnaryOperator和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);

    }  


为什么只有UnaryOperator<Double>才会出现编译错误(doub不是最终的)?如果变量声明从未改变,为什么会出现不同的结果?


郎朗坤
浏览 99回答 2
2回答

www说

就我而言(Java12),我在 和 中都遇到了DoubleUnaryOperator错误UnaryOperator。您的情况是,您正在重新分配doubwithoo函数结果,然后尝试使用doubin next 运算符。我引用的是:最终和有效最终之间的区别通俗地说,如果局部变量的初始值从未改变,那么它实际上就是final的——换句话说,将其声明为final不会导致编译失败。所以,经过检查我明白的是:如果变量是final,则它始终可以在 lambda 表达式中使用,因为不可能重新分配它(有 - 反射,但这是另一个主题)。effectively final当声明的变量保持不变时,该变量就会出现。如果您将 的结果分配oo给新声明的变量,那么您应该能够在o.我相信您试图实现10.6价值,示例如下: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 任何重新分配doub或ahh导致编译错误 (Java11)

12345678_0001

我无法重现您的声明,即一个编译而另一个不编译。对我来说,两者都不能编译。信息:java:编译模块“tuts”时发生错误信息:javac 1.8.0_192用于编译java源信息:9/14/2019 8:10 PM - 构建完成,2秒849毫秒C内有1个错误和0个警告:\Users\Philip\Code\tuts\src\test\java\tuts\UnaryOperatorTest.java 错误:(13, 60) java: 从 lambda 表达式引用的局部变量必须是最终的或有效的最终doub问题是,在使用 的 lambda 中创建新作用域后,您尝试在外部作用域中重新分配 to&nbsp;doub。doub如果您可以在 lambda 范围之外更改 的值,则 lambda 的功能将变得不确定。因此,来自外部作用域的值必须被声明final或者是“有效”最终的(意味着您遵循规则并且不要尝试在外部作用域中重新分配给它们)。如果您只需将结果分配给不同的变量(result,在下面的示例中),您就可以使用两种替代方案:import org.junit.Assert;import org.junit.Test;import java.util.function.DoubleUnaryOperator;import java.util.function.UnaryOperator;public class UnaryOperatorTest {&nbsp; &nbsp; @Test&nbsp; &nbsp; public void testDoubleUnaryOperator() {&nbsp; &nbsp; &nbsp; &nbsp; double doub = 10.0;&nbsp; &nbsp; &nbsp; &nbsp; DoubleUnaryOperator doubleUnaryOperator = d -> d + doub;&nbsp; &nbsp; &nbsp; &nbsp; double result = doubleUnaryOperator.applyAsDouble(0.3);&nbsp; &nbsp; &nbsp; &nbsp; Assert.assertEquals(10.3, result, Double.MIN_VALUE);&nbsp; &nbsp; }&nbsp; &nbsp; @Test&nbsp; &nbsp; public void testUnaryOperator() {&nbsp; &nbsp; &nbsp; &nbsp; double doub = 10.0;&nbsp; &nbsp; &nbsp; &nbsp; UnaryOperator<Double> unaryOperator = d -> d + doub;&nbsp; &nbsp; &nbsp; &nbsp; double result = unaryOperator.apply(0.3);&nbsp; &nbsp; &nbsp; &nbsp; Assert.assertEquals(10.3, result, Double.MIN_VALUE);&nbsp; &nbsp; }}(编辑)我已逐字复制并粘贴您的代码。FunctionalInterface从有问题的行号(31 和 36)可以看出,这两个示例&nbsp;都无法在 Java 8 中编译:然而,doub通过分配 to 来有效地实现最终result允许代码编译:&nbsp;
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java