簡體   English   中英

Java Lambda引用封閉對象:替換為私有靜態類?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM