过去几个月我一直在学习java,刚开始学习lambda函数。我最近切换了我的IDE并在这样的代码上注意到“可以用方法引用替换”的警告。
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
intList.add(3);
intList.forEach(num -> doSomething(num));
voiddoSomething(int num) {
System.out.println("Number is: " + num);
}
经过一番挖掘,我意识到这不是行
intList.forEach(num -> doSomething(num));
我可以使用
intList.forEach(this::doSomething);
这真是太棒了。几天前我甚至不知道lambdas并且正在使用for循环来做这样的操作。现在我用lambdas替换了我的for循环,甚至更好,我可以用方法引用替换我的lambdas。问题是我并不真正理解这一切是如何在内部发挥作用的。任何人都可以解释或提供一个很好的资源,解释如何调用doSomething函数,并在我们使用方法引用时将参数传递给它吗?
答案 0 :(得分:1)
双冒号运算符只是一个便利运算符,用于执行lambda正在执行的操作。有关详细信息,请查看此页面:https://javapapers.com/core-java/java-method-reference/
答案 1 :(得分:1)
双冒号只是用于定义lambda表达式的语法糖,其参数和返回类型与现有函数相同。它的创建是为了让Lambda能够更容易地与现有的代码库一起添加。
调用forEach
对象的List<Integer>
方法将任何实现Consumer
功能接口的对象作为参数。你的lambda num -> doSomething(num)
本身恰好符合这个界面的形式要求。
因此,您可以使用双冒号作为该lambda表达式的语法糖。
通常,如果您的对象obj
使用方法func
,它接受参数params...
,那么写obj::func
等同于lambda (params...) -> obj.func(params...)
。
在你的情况下,o
是this
(当前对象),它有一个方法doSomething()
,它接受一个整数参数,因此,this::doSomething
相当于num -> doSomething(num)
。
答案 2 :(得分:1)
鉴于你已经提到过,直到最近你才开始进入函数式编程,我希望尽可能保持简单和直接,但请注意,只要你提供的代码很少,我们就可以得到<从事物的高级视图以及低级视图中都可以看到很多。
无论我们使用internal iteration还是lambda表达式,任何人都可以解释或提供一个很好的资源来解释如何 调用doSomething函数并将参数传递给它 当我们使用方法参考?
如何调用doSomething
函数都留给库(method reference),所以基本上我们指定是什么不是我们为forEach方法提供的一个行为(一个函数)我们想要为源intList
的每个元素执行的行为(一个函数)的意义,而不一定是它应该如何进行它的工作
然后将其留给库,以便为源doSomething
的每个元素应用(执行)intList
的指定函数。
Method references可以看作是lambda只调用特定方法的简写。这里的好处是通过明确地引用特定的方法名称,您的代码获得了更好的可读性,因此,使其更易于阅读和遵循,并且在大多数情况下,使用方法引用读取代码作为问题陈述读取是一件好事。 / p>
同样重要的是要知道不能将任何给定的函数传递给forEach terminal operation,因为每个接受行为的方法都对允许的函数类型有限制。这是通过在functional interfaces包中使用java.util.function来完成的。
最后但并非最不重要的是,在重构方面,并不总是可以使用方法引用,也不总是使用lambdas expressions代替我们在Java-8之前使用的代码。但是,当您继续学习Java-8功能时,可以尝试一些改进代码的技巧: