Lambda表达式与方法参考[关闭]


114

IntelliJ一直建议我用方法引用替换我的lambda表达式。

两者之间有客观差异吗?


4
不完全是,我看不到任何物体!对我来说,这似乎像是个静态电话
Gerard 2014年

9
当然!但是“您也找不到” ...这是一个品味问题,我更担心更多技术方面的问题。实际上,正如您已经说过的一样,这对我来说是一个很好的答案。无论如何,正如IntelliJ提议的那样,我想通常比使用lambda(尽管对我来说不是)更能看到方法参考。
Gerard 2014年

15
Lambda表达式的代码被编译为合成方法,而方法引用不起作用(例外:特殊结构,如Type[]::new)。运行时生成的匿名类将是相同的。JRE在它们之间没有任何区别。因此,使用方法引用将在编译的代码中为您节省一个方法,另一方面,在进行逐步调试时不能停下来……
Holger 2014年

6
现在,这个问题将被解决……对于像我这样不知道lambda和引用之间的区别的所有用户来说,这实在太糟糕了,即使没有决定性的问题。我也想知道为什么没人敢回答这个问题?那是对我的正确答案。
杰拉德(Gerard)2014年

3
回答一个已经存在两年的封闭问题可能不是一个好主意,但是对于那些真正读过这个问题的人来说,这就是Oracle的教程(docs.oracle.com/javase/tutorial/java/javaOO/…)所说的:方法引用...是紧凑,易于阅读的lambda表达式,用于已经具有名称的方法。
明天

Answers:


187

让我对为什么我们在语言中添加此功能的原因提供一些看法,但显然我们并不一定要严格要求(所有方法引用都可以表示为lambda)。

请注意,没有正确的答案。任何说“总是使用方法ref代替lambda”或“总是使用lambda代替方法ref”的人都应该被忽略。

这个问题在本质上与“何时应该使用命名类还是匿名类”非常相似?答案是相同的:当您发现它更具可读性时。当然,在某些情况下肯定是一个或另一个,但中间有很多灰色,必须使用判断力。

方法refs背后的理论很简单:名称很重要。如果一个方法有一个名称,那么通常(但不总是如此!)更清晰易读,而不是用一个命令包(最终只是转过来调用它)来命名。

关于性能或关于字符计数的争论主要是红色鲱鱼,您应该忽略它们。目标是编写清晰易懂的代码。方法引用经常(但并非总是如此!)在此度量标准上获胜,因此我们将它们作为一个选项包括在内,以便在这些情况下使用。

关于方法引用是否澄清或模糊意图的关键考虑因素是从上下文是否明显看出所表示的函数的形状是什么。在某些情况下(例如,map(Person::getLastName)从上下文中可以很明显地看出,需要将一个事物映射到另一事物的函数,而在这种情况下,方法引用很有用。在其他情况下,使用方法ref要求读者想知道哪种类型函数的功能正在描述中;这是一个警告信号,即使更长,lambda也可能更具可读性。

最后,我们发现大多数人起初避开方法引用,因为他们觉得自己比lambda更新颖,更奇怪,因此最初发现它们“可读性差”,但是随着时间的流逝,当他们习惯了语法时,通常会更改其行为,并在可能时偏向于方法引用。因此请注意,您自己的主观初始“难以理解的”反应几乎肯定会带来一些熟悉性方面的偏见,并且您应该给自己一个机会,在提出风格上的见解之前先对两者都感到满意。


25
@杰拉德谢谢您,这将是一个更好的答案。
Yassin Hajaj'3

3
@Gerard听起来好像Brian在说“不,没有”
dj18

Brian,使用相同方法的方法引用和lambda会得到不同的结果。它们不应该互换吗?
mFeinstein '18

@mFeinstein对于每个方法引用,都有一个等效的lambda(您可能会或可能不会使用)。将代码作为问题发布吗?
布莱恩·格茨

我想要,但是我担心代码可能太大了,因为它是a LiveData内的一个Android ,Fragment我将Event其转换为由ViewModel... 触发的...,而当Android返回相同的Fragment.. 时,会发生不同的行为。 .so我很难简化一个问题
mFeinstein

10

由多个语句组成的长lambda表达式可能会降低代码的可读性。在这种情况下,提取方法中的那些语句并引用它可能是一个更好的选择。

另一个原因可能是可重用性。无需复制并粘贴几个语句的lambda表达式,您可以构造一个方法并从代码的不同位置调用它。


3
比较:houses.map(House::getName)houses.map(h -> h.getName())。Lambda少占用两个字符。的确,类型不是显式的,但是任何IDE都会告诉您,此外,当类型明显时,应使用lambda。我可能会同意您的可重用性,但是lambda很小,因此可以将它们链接起来,而不用创建大型的特定方法。从这个意义上讲,小方法比某些大而复杂的方法更可重用,并且由于lambda的清晰(在某种程度上是冗长),它们仍然易于阅读。
杰拉德2014年

11
我和杰拉德在一起。当您移出代码时,可读性实际上会受到影响,因此您必须跳到该代码以继续阅读,然后再跳回去。您希望所有相关代码都放在同一位置。同样,这House是一个非常好的例子。那呢ThreeStoryRedBrickHouseWithBlueDoors?我更喜欢多参数Lambda的方法引用,有时还要强调Lambda只是关于单个方法的调用。有少去错的方法参考:你可能在使用现场拼错的说法,不小心指从外部范围等变量
马尔科Topolnik

@杰拉德我不同意你的第一句话。如果使用描述得当的方法名称,并且提取了大量代码,则移动代码可提高可读性。如果您使用混淆方法名称,则我同意。
Torsten
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.