我在研究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;
}
max是一个方法指针吗?一个正常的静态方法如何转换为IntBinaryOperator?
::操作符是在Java 8中引入的,用于方法引用。方法引用是只执行一个方法的lambda表达式的简写语法。下面是方法引用的一般语法:
Object :: methodName
我们知道可以使用lambda表达式,而不是使用匿名类。但有时,lambda表达式实际上只是对某些方法的调用,例如:
Consumer<String> c = s -> System.out.println(s);
为了使代码更清晰,你可以将lambda表达式转换为方法引用:
Consumer<String> c = System.out::println;
我发现这个来源非常有趣。
事实上,是lambda变成了双冒号。双冒号可读性更好。
我们遵循以下步骤:
步骤1
// We create a comparator of two persons
Comparator c = (Person p1, Person p2) -> p1.getAge().compareTo(p2.getAge());
步骤2
// We use the interference
Comparator c = (p1, p2) -> p1.getAge().compareTo(p2.getAge());
步骤3
// The magic using method reference
Comparator c = Comparator.comparing(Person::getAge);
这是Java 8中的一个方法引用。Oracle文档在这里。
如文件所述……
方法引用Person::compareByAge是对静态对象的引用
方法。
类的实例方法的引用示例
特定对象:
class ComparisonProvider {
public int compareByName(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
public int compareByAge(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
ComparisonProvider myComparisonProvider = new ComparisonProvider();
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
方法引用myComparisonProvider::compareByName调用方法compareByName
它是对象myComparisonProvider的一部分。JRE会推断
方法类型参数,在本例中为(Person, Person)。