[英]Java Lambda Referencing Enclosing Object: Replace with Private Static Class?
A Java lambda referencing an element from its enclosing scope holds a reference to its enclosing object. 引用其封闭范围内的元素的Java lambda包含对其封闭对象的引用。 A contrived example, with lambda holding ref to MyClass:
一个人为的例子,lambda持有ref给MyClass:
class MyClass {
final String foo = "foo";
public Consumer<String> getFn() {
return bar -> System.out.println(bar + foo);
}
}
This is problematic if the lifetime of the lambda is long; 如果lambda的寿命很长,这是有问题的; then we've got a ref to MyClass that is long-lived, when it would have otherwise gone out of scope.
然后我们得到一个长寿的MyClass引用,否则它会超出范围。 Here we can optimize by replacing the lambda with a private static class, so that we're only holding a reference to the String we need rather than to the entire class:
在这里我们可以通过用私有静态类替换lambda来优化,这样我们只需要对我们需要的String进行引用,而不是对整个类:
class MyClass {
private static class PrintConsumer implements Consumer<String> {
String foo;
PrintConsumer(String foo) {
this.foo = foo;
}
@Override
public void accept(String bar) {
System.out.println(bar + foo);
}
}
final String foo = "foo";
public Consumer<String> getFn() {
return new PrintConsumer(foo);
}
}
Unfortunately this is super verbose and destroys the nice syntax we get from using (effectively final) variables from enclosing scope in lambdas. 不幸的是,这是超级冗长的,并且破坏了我们从lambdas中封闭范围中使用(有效最终)变量获得的良好语法。 Is this technically optimal?
这在技术上是最佳的吗? Is there always a tradeoff here between nice syntax and the possibility of keeping a ref longer than necessary?
是否总是在良好的语法和保持ref超过必要的可能性之间进行权衡?
class MyClass {
final String foo = "foo";
private Consumer<String> getFn() {
String localFoo = foo;
return bar -> System.out.println(bar + localFoo);
}
}
Now, the lambda only captures local variables inside of getFn()
. 现在,lambda只捕获
getFn()
局部变量。 MyClass.this
is no longer captured. MyClass.this
不再被捕获。
class MyClass {
final String foo = "foo";
private Consumer<String> getFn() {
return getFn(foo);
}
private static Consumer<String> getFn(String localFoo) {
return bar -> System.out.println(bar + localFoo);
}
}
A combination of Lukas Eder's local-final-variable and helper-method-delegation solutions: Lukas Eder的本地最终变量和辅助方法委派解决方案的组合:
class MyClass {
final String foo = "foo";
private Consumer<String> getFn() {
return apply(
foo,
localFoo -> bar -> System.out.println(bar + localFoo)
);
}
private static <IN, OUT> OUT apply(
final IN in,
final Function<IN, OUT> function
) {
return function.apply(in);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.