引用而不执行

时间:2016-02-22 10:24:19

标签: lambda java-8 method-reference

根据这个article,方法引用被定义为一个没有被执行的引用的方法或构造函数,任何人都可以解释这是怎么可能的?

例如:

public void main String(args[]) {
     List<Integer> numbers = Arrays.asList(1, 2, 3);
     // Below is a method reference that is referenced and being executed on run (prints the numbers!!)
     numbers.forEach(System.out::println);
}

如果有人能够解释在没有被执行的情况下引用了哪些陈述&#39;意思是,非常感谢:)

2 个答案:

答案 0 :(得分:2)

当您致电numbers.forEach(System.out::println)时,您会引用System.out::println方法,但不会执行该方法。例如,如果numbers列表为空,则永远不会执行此方法。另一方面,有了这个方法引用,forEach方法可以在内部调用此引用多次(在这种情况下:对于每个列表元素)。

当您使用等效的匿名类重写此代码时,可能会更容易理解:

 numbers.forEach(new Consumer<Integer>() {
     public void accept(Integer num) {
         System.out.println(num);
     }
 });

在这里你可以看到方法引用实际上是Consumer类型的辅助对象的创建,而没有实际调用引用的方法。

答案 1 :(得分:2)

您的陈述numbers.forEach(System.out::println);

的内联版本
Consumer<Integer> c=System.out::println;
numbers.forEach(c);

这应该更好地说明第一行创建对println中找到的PrintWriter实例的方法System.out的引用,但不执行它。它不会打印任何东西 - 它甚至不知道要打印什么。要打印的对象是创建的Consumer accept方法的参数。

第二行numbers.forEach(c)最终会打印每个数字,因为指定的Consumer已创建为参考System.out::printlnforEach方法接收任意Consumer并通过为每个元素调用所述accept方法为每个元素执行封装操作,并将该元素作为参数传递。

当然,您可以内联变量c获取原始语句numbers.forEach(System.out::println);,但是,消费者创建和执行之间的差异不是那么明显,但也与此用例无关。通常,您可以使Consumer比单个用例更长。