比较用于将双精度数加到双精度数的两种运算符类型: DoubleUnaryOperator 和 UnaryOperator
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
答案 0 :(得分:0)
在我的情况下(Java12),我在DoubleUnaryOperator
和UnaryOperator
上都遇到了错误。
您遇到的情况是,您要用doub
函数结果重新分配oo
,然后再尝试在下一个运算符中使用doub
。
我引用的是:Difference between final and effectively 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)
答案 1 :(得分:0)
我无法复制您声明一个编译而另一个没有编译的陈述。对我来说,都不编译。
信息:java:编译模块“ tuts”时发生错误 信息:javac 1.8.0_192用于编译Java源代码 信息:9/14/2019 8:10 PM-构建完成,出现1个错误和0 2秒849毫秒内发出警告 C:\ Users \ Philip \ Code \ tuts \ src \ test \ java \ tuts \ UnaryOperatorTest.java 错误:(13,60)java:从lambda引用的局部变量 表达必须是最终的或实际上是最终的
问题在于,您是在使用doub
的lambda中创建新作用域之后,尝试在外部作用域中重新分配给doub
。
如果您可以在Lambda范围之外更改doub
的值,则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);
}
}
(编辑)我已逐字复制并粘贴了您的代码。从有问题的行号(31和36)可以看出,FunctionalInterface
示例都无法在Java 8中编译: