我发现了一个使用 Stream API 的有趣示例:
Stream<String> stream = Stream.of("w", "o", "l", "f");
BiConsumer<StringBuilder, String> append = StringBuilder::append;
StringBuilder collected = stream.collect(StringBuilder::new, append, StringBuilder::append);
System.out.println(collected); //it works correctly
Run Code Online (Sandbox Code Playgroud)
Stream.collect 接受三个参数:
Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner
Run Code Online (Sandbox Code Playgroud)
BiConsumer 接受两个参数并且不返回任何内容。为什么这条线可以编译和工作?
BiConsumer<StringBuilder, String> append = StringBuilder::append;
Run Code Online (Sandbox Code Playgroud)
StringBuilder 没有 void 方法 append(java.lang.StringBuilder, java.lang.String)。
JLS 15.13.3或多或少指定接收者(调用方法的对象)可以成为功能接口的第一个参数:
\n\n\n如果形式为ReferenceType :: [TypeArguments] Identifier,则调用方法的主体类似地具有编译时声明的方法调用表达式的效果,该编译时声明是方法引用表达式的编译时声明。方法调用表达式的运行时评估如 \xc2\xa715.12.4.3、\xc2\xa715.12.4.4 和 \xc2\xa715.12.4.5 中指定,其中:
\n调用模式源自 \xc2\xa715.12.3 中指定的编译时声明。
\n如果编译时声明是实例方法,则目标引用是调用方法的第一个形参。否则,就没有目标参考。
\n如果编译时声明是实例方法,则方法调用表达式的参数(如果有)是调用方法的第二个和后续形式参数。否则,方法调用表达式的参数是调用方法的形式参数。
\n
编译时声明实际上是一个实例方法,因此 成为StringBuilder调用方法的第一个参数,并且String成为第二个参数。
换句话说,方法引用SomeClass::instanceMethod相当于 lambda (SomeClass receiver, args...) -> receiver.instanceMethod(args...)。
| 归档时间: |
|
| 查看次数: |
951 次 |
| 最近记录: |