2015-01-19 6 views
12

natknąłem się na następujący kod Java, który jest przy użyciu metody odniesienia dla System.out.printlnCo jest odpowiednikiem wyrażenie lambda dla System.out :: println

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); 
     } 
    } 
} 

Co to jest równoważne wyrażenie lambda dla System.out::println?

+3

Nie jest to jednak dokładnie funkcjonalne :-) –

+0

@StephenC może sugerować, dlaczego? – Steve

+4

Cóż 'println' nie jest funkcją wolną od skutków ubocznych ... jest to. –

Odpowiedz

22

Metoda referencyjna System.out::println oceni System.out pierwszy, a następnie utworzyć odpowiednik wyrażenia lambda, która przechwytuje oszacowanych wartości. Zwykle używałbyś
o->System.out.println(o), aby osiągnąć to samo, co odwołanie do metody, ale to wyrażenie lambda będzie oceniać System.out za każdym razem, gdy metoda zostanie wywołana.

Więc dokładny równoważne byłoby:

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

który będzie różnica jeśli ktoś powołuje System.setOut(…); pomiędzy.

+0

Rozumiem, że cel wywołania odwołania do metody jest oceniany "po pierwszym napotkaniu jego deklaracji", co jest dla mnie logiczne. Ale czy istnieje część jls, która wyraźnie to mówi (naprawdę próbowałem ją znaleźć ...). Jeśli cel wywołania jest metodą, można przechwycić metodę i "to" na przykład, a nie rzeczywisty obiekt, który zwraca metoda ... o ile rozumiem. Czy może to się stało całkowicie błędne? – Eugene

+0

nieważne ... '' Po pierwsze, jeśli wyrażenie referencyjne metody rozpoczyna się od wyrażenia nazwa lub podstawowa, to podwyrażenie jest oceniane " – Eugene

2

To:

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

albo jeszcze prościej:

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