System.out::println的等效lambda表达式是什么?

27
我发现了以下使用方法引用调用System.out.println的Java代码:

我发现了以下使用方法引用调用System.out.println的Java代码:

class SomeClass {
    public static void main(String[] args) {
           List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9);
           numbers.forEach(System.out::println);
        }
    }
}

System.out::println 的等效 lambda 表达式是什么?


4
它并不完全实用,不过 :-)。 - Stephen C
@StephenC,你能否建议一下为什么? - Steve
6
那么 println 函数几乎没有副作用...是吗? - Stephen C
2个回答

61

方法引用 System.out::println 会先评估 System.out,然后创建等效于 lambda 表达式的东西,该表达式捕获了评估后的值。通常,您会使用
o -> System.out.println(o) 来实现与方法引用相同的功能,但是每次调用方法时,此 lambda 表达式都会重新计算 System.out

因此,一个完全等效的表达式是:

PrintStream p = Objects.requireNonNull(System.out);
numbers.forEach(o -> p.println(o));

如果有人在其中调用了 System.setOut(…);,这将产生影响。

Translated:

如果有人在其中调用了 System.setOut(…);,这将产生影响。


我确实理解方法引用的调用目标是在“首次遇到其声明时”进行评估,这对我来说是合乎逻辑的。但是否有JLS的某个部分明确说明了这一点(我确实试图找到它……)?如果调用目标是一个方法,那么可以捕获该方法和例如this,而不是该方法返回的实际对象……就我所理解的而言。还是我完全弄错了? - Eugene
不用在意... 首先,如果方法引用表达式以ExpressionName或Primary开头,则会评估此子表达式。 - Eugene

6

这是:

numbers.forEach(i -> {System.out.println(i);});

甚至更简单:
numbers.forEach(i -> System.out.println(i));

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