为什么在捕获静态字段值时,等效的lambda表达式和方法引用的行为会有所不同? [英] Why do equivalent lambda expression and method reference behave differently when capturing static field value?

查看:207
本文介绍了为什么在捕获静态字段值时,等效的lambda表达式和方法引用的行为会有所不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Java lambdas和方法引用行为有点困惑。例如,我们有这样的代码:

I'm a little bit confused about Java lambdas and method references behaviour. For ex., we have this code:

import java.util.function.Consumer;

public class Main {

    private static StringBuilder sBuilder = new StringBuilder("1");

    public static void main(String[] args) {
        Consumer<String> consumer = s -> sBuilder.append(s);
        sBuilder = new StringBuilder("2");
        consumer.accept("3");
        System.out.println(sBuilder);
    }

}

输出:

23

这按预期工作,但如果我们更换

This works as expected, but if we replace

s - > sBuilder.append(s)

with

sBuilder :: append

输出将是:

2

您有任何想法如何解释这个吗?这不是一回事吗?谢谢。

Have you any ideas how to explain this? This isn't the same things? Thanks.

推荐答案

在lambda表达式中,捕获 sBuilder 字段,但没有评估。只有在调用相应的函数接口方法时才会对其进行求值。此时, sBuilder 引用创建的新实例,并使用

In the lambda expression, the sBuilder field is captured, but not evaluated. It will only be evaluated when the corresponding function interface method is invoked. At that point, the sBuilder references the new instance created and assigned to the field with

sBuilder = new StringBuilder("2");

在方法参考中, sBuilder 字段立即进行评估,以生成 Consumer 实例。该值引用在静态初始值设定项中创建的实例

In the method reference, the sBuilder field is evaluated immediately to produce a Consumer instance. That value references the instance created in the static initializer

private static StringBuilder sBuilder = new StringBuilder("1");

消费者将在那一个上运作。你打印新的。

and the Consumer will operate on that one. You print the new one.

来自Java语言规范,关于方法参考的运行时评估

From the Java Language Specification, concerning the Run-Time Evaluation of Method References


调用方法的主体取决于方法
引用表达式的形式,如下所示:

The body of an invocation method depends on the form of the method reference expression, as follows:

如果表单是 ExpressionName :: [TypeArguments] Identifier
Primary :: [TypeArguments] Identifier ,然后
调用方法的主体具有
a编译时声明的方法调用表达式的效果,这是方法引用表达式
的编译时声明。方法
调用表达式的运行时评估在§15.12.4.3,§15.12.4.4和$ b $b§15.12.4.5中规定,其中:

If the form is ExpressionName :: [TypeArguments] Identifier or Primary :: [TypeArguments] Identifier, then the body of the invocation method has the effect of a method invocation expression for a compile-time declaration which is the compile-time declaration of the method reference expression. Run-time evaluation of the method invocation expression is as specified in §15.12.4.3, §15.12.4.4, and §15.12.4.5, where:


  • 调用模式源自§15.12.3中指定的编译时声明。

  • The invocation mode is derived from the compile-time declaration as specified in §15.12.3.

目标引用是 ExpressionName Primary 的值,在方法引用表达式为$时确定b $ b已评估。

The target reference is the value of ExpressionName or Primary, as determined when the method reference expression was evaluated.

方法调用表达式的参数是调用方法的形式参数。

The arguments to the method invocation expression are the formal parameters of the invocation method.

这篇关于为什么在捕获静态字段值时,等效的lambda表达式和方法引用的行为会有所不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆