最近我一直在摆弄新的java8功能,以便更好地理解它们.
当Stream.filter我尝试一些东西时,我遇到了Predicate.java其中我找到了以下isEqual方法实现的来源:
/**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
Run Code Online (Sandbox Code Playgroud)
让我惊讶的是这条线:: object -> targetRef.equals(object);.
也许我正在大力推翻这个,但我不禁立刻想到为什么那条线不是: targetRef::equals;这样的:
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: targetRef::equals;
}
Run Code Online (Sandbox Code Playgroud)
在我看来,不必要地创建一个lambda.
除非我遗漏了某些东西,否则我会做同样的事情.(他们是一样的吗?)有没有理由选择当前的实施?或者这只是一个非常小的东西,它只是被忽视或没有人真正关心.
猜猜实际上会产生一个额外的问题:使用一种方式比另一种方式有什么好处吗?像某种(可能是非常小的)性能奖金?
为什么这样做?
纯粹的推测,但也许,当它被写入时,开发人员对 - >和可能的::当时甚至不起作用更为舒服.这些库是在修复编译器中的错误时编写的.
没有办法知道,甚至写它的人可能都不记得了.
无论使用方法引用还是闭包语法,在大多数情况下都会创建相同数量的对象(如本例所示)
猜猜实际上会产生一个额外的问题:使用一种方式比另一种方式有什么好处吗?像某种(可能是非常小的)性能奖金?
使用方法引用意味着少一个方法调用.这可能会对内联产生间接影响,因为默认情况下级别数限制为9.例如
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
Consumer<String> lambda = s-> printStackTrace(s);
lambda.accept("Defined as a lambda");
Consumer<String> methodRef = Main::printStackTrace;
methodRef.accept("Defined as a method reference");
}
static void printStackTrace(String description) {
new Throwable(description).printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
版画
java.lang.Throwable: Defined as a lambda
at Main.printStackTrace(Main.java:15)
at Main.lambda$main$0(Main.java:6)
at Main.main(Main.java:7)
java.lang.Throwable: Defined as a method reference
at Main.printStackTrace(Main.java:15)
at Main.main(Main.java:10)
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,编译器生成了一个Main.lambda$main$0包含实际调用的代码的方法printStackTrace
使用其中一个或另一个产生更大差异的地方在于您可以捕获(保存值)或不捕获lambda.非捕获lambda仅创建一次.
例如
Consumer<String> print1 = System.out::println; // creates an object each time
Consumer<String> print2 = s->System.out.println(s); // creates an object once.
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,如果您调用System.setOut它将忽略此更改,因为它具有要写入的PrintStream的自己的副本.
| 归档时间: |
|
| 查看次数: |
1271 次 |
| 最近记录: |