简体   繁体   English

Java Lambda引用封闭对象:替换为私有静态类?

[英]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超过必要的可能性之间进行权衡?

Assign your member to a local variable first: 首先将您的成员分配给本地变量:

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不再被捕获。

Another option, slightly more verbose, delegate to a helper method: 另一个选项,稍微详细一点,委托给一个帮助方法:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM