在研究Java 8函数编程时,我发现了以下明显的不一致之处。下面的两个构造应等效:
public static BiFunction<Integer, Integer, Integer> addTwoIntegers (Integer i1, Integer i2)
{
return new BiFunction<Integer, Integer, Integer>()
{
@Override
public Integer apply(Integer i1, Integer i2)
{
return i1 +i2;
}
};
}
public static BiFunction<Integer, Integer, Integer> addTwoIntegers2 (Integer i1, Integer i2)
{
return (i1x, i2x) -> i1 + i2;
}
第一个声明是传统的匿名类,而第二个声明是lambda函数,但否则它们应该等效。现在,按如下方式调用它们:
System.out.println("addTwoIntegers: " + addTwoIntegers(new Integer(0), new Integer(0)).apply(new Integer(5), new Integer(7)));
System.out.println("addTwoIntegers2: " + addTwoIntegers2(new Integer(0), new Integer(0)).apply(new Integer(5), new Integer(7)));
我得到:
addTwoIntegers: 12
addTwoIntegers2: 0
因此,这两个声明不相等,很难接受;或者,如果它们相等,则假定它们在相同的上下文中使用相同的参数被调用,它们应产生相同的结果。这不是矛盾之处吗?
在此先感谢可以遮挡某些灯光的人。
亲切的问候,尼古拉斯
答案 0 :(得分:2)
声明不是等效的。由于variable shadowing,第一种方法可以转换为以下功能:
public static BiFunction<Integer, Integer, Integer> addTwoIntegers(Integer i1, Integer i2) {
return (i1x, i2x) -> i1x + i2x;
}
第二个方法函数表达式引用了addTwoIntegers2
方法参数i1
和i2
,而不是函数参数i1x
和i2x
。 i1
在函数闭包中是i2
可用的,因为它们都是0
,结果是0
。
答案 1 :(得分:1)
所以两个声明都不相等,这很难 承认,
第一个示例中未使用addTwoIntegers
即i1
和i2
的方法参数。
public static BiFunction<Integer, Integer, Integer> addTwoIntegers(Integer i1, Integer i2) {
// to aid to debugging
System.out.println(String.format("In addTwoIntegers i1: %s, i2: %s", i1, i2));
return new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer i1, Integer i2) {
// see the difference in value as you run
System.out.println(String.format("In apply i1: %s, i2: %s", i1, i2));
return i1 + i2;
}
};
}
作为补充,i1
和i2
的范围作为apply
方法的方法参数是匿名类中该方法的本地代码,这就是您的代码所表示的。
如果要实现添加到Integer
(并返回Integer
)中,另一种更简洁的方法是在您要使用的范围内定义BinaryOperator<Integer>
可能将实现重用为:
BinaryOperator<Integer> addTwoIntegers = Integer::sum; // (a,b) -> a+b
,然后将其简单地用作
System.out.println("addTwoIntegers: " + addTwoIntegers.apply(5, 7));