Java 8中实例方法引用类型有什么区别?

24

Java 8引入了方法引用,文档描述了四种类型

我的问题是两种实例类型之间有什么区别?

  1. 对特定对象的实例方法的引用。
  2. 对特定类型的任意对象的实例方法的引用。

这两者都是引用,但有何显着不同?解析它们所使用的类型推断是否不同?在他们的示例中,其中一个是闭包,另一个是lambda,这重要吗?与方法参数的数量是否有关?


2
我在http://baddotrobot.com/blog/2014/02/18/method-references-in-java8/写下了我的结论。 - Toby
3个回答

17
  1. myString::charAt 接受一个 int 参数并返回一个 char 值,可以用于任何按照该方式工作的 lambda 表达式。它本质上的翻译是 index -> myString.charAt(index)

  2. String::length 接受一个 String 参数并返回一个 int 值。它本质上的翻译是 string -> string.length()

  3. String::charAt 本质上的翻译是 (string, index) -> string.charAt(index)


5
对于你最后一个观点,是的,String::charAt 相当于 (s, i) -> s.charAt(i)。第一个参数变成了接收者,并且后续参数左移了一个位置。相当微妙。 - Stuart Marks
事实上,使用 Lambda 表达式更清晰,我不知道为什么要使用方法引用... - user1169587

3
他们的意思是你具有以下功能:
1) 例如可以使用this::someFunction;,这将返回当前对象的someFunction引用。
2) 例如可以使用String::toUpperCase,这将返回一般情况下StringtoUpperCase方法。
我不确定是否有实际的行为差异,我认为这就像您也可以在实例变量上调用静态方法一样。

1
我写了一个结论我来到这里的原因,下面是摘要。
Oracle将四种方法引用描述如下。

enter image description here

他们应该写的是:

enter image description here

我发现他们对前两个描述有些混淆(“引用静态方法”和“引用特定对象的实例方法”),我认为这实际上是一个类静态和一个对象之间的区别。
我更喜欢将第一个看作预先知道的特定对象的实例方法,第二个看作任意对象的实例方法,稍有趣味的是,这意味着第一个是闭包,第二个是lambda。一个是绑定的,另一个是未绑定的。
闭包和lambda之间的方法引用的区别可能有点学术化,但至少它比Oracle不太有帮助的描述更加正式。如果您对闭包和lambda之间的区别感兴趣,请查看this post
总结
两种实例方法引用的区别很有趣,但基本上是学术性的。有时,您需要传递一些内容,而其他时候,lambda的使用将为您提供它。我的抱怨是针对Oracle的文档。他们对这个区别非常重视,但未能以易于理解的方式描述它。这是规范参考材料,但却令人困惑。
还有一两个微妙之处,我写了一篇wrote up

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接