Lambda 和方法引用对非最终变量使用不同的方法。为什么?

问题描述 投票:0回答:1

我不懂这个。

在 lambda 表达式中,您根本无法引用非最终变量。

// doesn't compile
    @Test
    void methodReferenceTest() {
        String message = "123";
        message = "1234";
        Supplier<Integer> messageLengthSupplier = () -> message.length();
        System.out.print("Message length: ");
        message = "12345";
        System.out.print(messageLengthSupplier.get());
    }

但是在方法引用中,您可以这样做,但是方法引用之后的任何重新分配都将被忽略。

    @Test
    void methodReferenceTest() {
        String message = "123";
        message = "1234";
        Supplier<Integer> messageLengthSupplier = message::length;
        System.out.print("Message length: ");
        message = "12345";
        System.out.print(messageLengthSupplier.get()); // prints 4
    }

为什么 Java 创建者没有对 lambda 和方法引用使用一种方法?

有一些与 Java 创建者的设计决策相关的问题(示例),所以我相信这个问题与其他问题一样好(并且与主题一样)。

我不满意“因为方法引用就像方法句柄”(所以我不希望它被标记为问题的重复项)。那么,为什么它们的行为就像方法句柄一样?这只是重新表述问题而不是回答问题。

java lambda
1个回答
0
投票

当你执行

message::length
时,你正在获取message变量(这是一个字符串)的
,然后说“我想要这个字符串的
length
方法”。这就是为什么后续对
message
的赋值对方法没有影响 - 方法引用仍然引用原始字符串对象!

相比之下,当您使用 lambda 表达式时,至少在概念上,您捕获了

message
变量本身 - 在实际调用匿名函数之前不会检查其值。这可能会产生一些棘手的情况,例如,如果匿名函数的生存期超出了它创建的范围。有些语言(例如大多数 Lisp 方言和 Python)允许这样做。 Java 通过强制变量“有效地最终”来应对这一问题。另请参阅 维基百科上的“funarg 问题”

© www.soinside.com 2019 - 2024. All rights reserved.