为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

郎朗坤 2023-07-28 16:12:26
比较用于将双精度数添加到双精度数的两个运算符类型: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不是最终的)?如果变量声明从未改变,为什么会出现不同的结果?
查看完整描述

2 回答

?
www说

TA贡献1775条经验 获得超8个赞

就我而言(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)


查看完整回答
反对 回复 2023-07-28
?
12345678_0001

TA贡献1802条经验 获得超5个赞

我无法重现您的声明,即一个编译而另一个不编译。对我来说,两者都不能编译

信息: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 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 {


    @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);

    }


}

(编辑)我已逐字复制并粘贴您的代码。FunctionalInterface从有问题的行号(31 和 36)可以看出,这两个示例 都无法在 Java 8 中编译:

https://img1.sycdn.imooc.com//64c378a000015a8606560503.jpg

然而,doub通过分配 to 来有效地实现最终result允许代码编译: 

https://img1.sycdn.imooc.com//64c378b4000181ac06530555.jpg

查看完整回答
反对 回复 2023-07-28
  • 2 回答
  • 0 关注
  • 98 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信