我正在探索Java 8来源并发现代码的这一特定部分非常令人惊讶:
// Defined in IntPipeline.java
@Override
public final OptionalInt reduce(IntBinaryOperator op) {
return evaluate(ReduceOps.makeInt(op));
}
@Override
public final OptionalInt max() {
return reduce(Math::max); // This is the gotcha line
}
// Defined in Math.java
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
是Math::max
类似方法指针?如何正常static
方法转换为IntBinaryOperator
?
答案
通常,有人会打电话给reduce
方法使用Math.max(int, int)
如下:
reduce(new IntBinaryOperator() {
int applyAsInt(int left, int right) {
return Math.max(left, right);
}
});
这需要大量的语法来打电话Math.max
。那就是Lambda表情发挥作用的地方。由于Java 8,因此允许以更短的方式做同样的事情:
reduce((int left, int right) -> Math.max(left, right));
这是如何运作的?Java编译器"检测",您要实现一种接受两个的方法int
s并返回一个int
。这等同于一个接口的唯一方法的形式参数IntBinaryOperator
(方法的参数reduce
您想打电话)。因此,编译器为您完成其余的工作 - 它只是假设您想实现IntBinaryOperator
。
但是Math.max(int, int)
本身符合正式要求IntBinaryOperator
,可以直接使用。因为Java 7没有任何允许方法本身作为参数传递的语法(您只能通过方法结果,但切勿通过方法参考),所以::
语法是在Java 8中引入的,用于参考方法:
reduce(Math::max);
请注意,这将由编译器解释,而不是在运行时由JVM解释!尽管它为所有三个代码段都产生不同的字节码,但在语义上是相等的,因此可以认为最后两个版本是简短的(并且可能更有效)IntBinaryOperator
上面的实现!
(也可以看看lambda表达式的翻译)