【问题标题】:What would the scope change from converting a Java anonymous inner class into a Lambda expression look like?将 Java 匿名内部类转换为 Lambda 表达式后,范围会发生什么变化?
【发布时间】:2017-01-24 22:37:51
【问题描述】:

来自Java8 Lambdas vs Anonymous classes:
“...[Anonymous Inner Classes] 引入了一个新的范围。也就是说,名称是从 AIC 的超类和接口解析的,并且可以隐藏出现在词法封闭环境中的名称。对于 lambda,所有名称都按词法解析。”

鉴于上述关于范围的陈述,如果简单地转换为 Lambda,执行方式不同的 Java 匿名内部类会是什么样子?

这两段代码看起来行为相同:

    button.addClickHandler(clickEvent -> doSomething());

    button.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                doSomething();
            }
    });

但是如果内部方法是doSomething(this) 会是这样吗?还是doSomething(myVariable)

范围的变化很重要以及它的行为方式的一个例子是非常棒的。我知道 Lambda 在其他方面与匿名内部类不同,但我还没有找到任何好的解释。

【问题讨论】:

  • 您想不出这样的场景:代码的行为(或编译)可能会因this 所指的内容而有所不同?这应该不会太难。
  • 具体参考this:我的问题可以解读为“AIC 和 Lambda 之间的范围差异是否使得 this 在两者之间有所不同?如果是,它指向什么?在 Lambda 的情况下?”
  • 是的,有区别。在匿名类中,它指向匿名类实例。在 lambda 中,它指向 lambda 之外的任何内容。
  • 请注意,有一个 JEP 正在考虑中,它可能会在未来的版本中取消对 lambdas 中变量阴影的限制。

标签: java lambda scope


【解决方案1】:

考虑以下示例:

import java.util.function.Function;

public class Main {
    private static abstract class ParentClass implements Function<String, String> {
        protected String prefix = "parent_class_";
    }

    public static void main(String... args) {
        String prefix = "local_";
        printString("test", new ParentClass() {
            @Override
            public String apply(String s) {
                return prefix + s;
            }
        });
        printString("test", s -> prefix + s);
    }

    private static void printString(String baseString, Function<String, String> stringMapper) {
        System.out.println(stringMapper.apply(baseString));
    }
}

打印出来

父类测试

本地测试

特别是,AIC 中的 prefix 指的是父类中的字段,而 lambda 中的 prefix 指的是局部变量。

【讨论】:

    【解决方案2】:

    发件人:Lambda this reference in java
    “当您在内部类的实例中使用 this 时,您正在引用内部类的实例。lambda 表达式不是内部类,这不是引用 lambda 表达式的实例。它引用的是实例您在其中定义 lambda 表达式的类。在您的情况下,它将是 Main 的一个实例。但由于您在静态方法中,因此没有实例。"

    所以,由于 Lambda 不是内部类,而是一个方法,Lambda 函数的范围将是封闭类的范围,而不是 Lambda(就像这种情况一样)对于匿名内部类)。

    【讨论】:

    • Lambda 不是(必然)静态方法。链接问题中的 lambda 只是在静态上下文中定义的。
    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 2013-04-24
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    相关资源
    最近更新 更多