[英]Java Lambda Referencing Enclosing Object: Replace with Private Static Class?
引用其封閉范圍內的元素的Java lambda包含對其封閉對象的引用。 一個人為的例子,lambda持有ref給MyClass:
class MyClass {
final String foo = "foo";
public Consumer<String> getFn() {
return bar -> System.out.println(bar + foo);
}
}
如果lambda的壽命很長,這是有問題的; 然后我們得到一個長壽的MyClass引用,否則它會超出范圍。 在這里我們可以通過用私有靜態類替換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);
}
}
不幸的是,這是超級冗長的,並且破壞了我們從lambdas中封閉范圍中使用(有效最終)變量獲得的良好語法。 這在技術上是最佳的嗎? 是否總是在良好的語法和保持ref超過必要的可能性之間進行權衡?
class MyClass {
final String foo = "foo";
private Consumer<String> getFn() {
String localFoo = foo;
return bar -> System.out.println(bar + localFoo);
}
}
現在,lambda只捕獲getFn()
局部變量。 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);
}
}
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.