2015-04-17 18 views
8

Przeczytałem w książce (Fischer's Java Closures i Lambda, Apress 2015), że odniesienia do metody są lepsze od wyrażeń lambda. Z mojego punktu widzenia wyrażenie lambda jest łatwiejsze do zrozumienia dla programistów używających innych języków. Więc dlaczego mówi, że odniesienie do metody jest lepsze? Czy pisanie wyrażeń lambda jest złym zwyczajem w Java 8?Wyrażenie lambda lub odwołanie do metody?

+1

Nie jest to "zła praktyka" oznacza po prostu, że nie nadaje się do wielokrotnego użytku i nie może samo się odwoływać (rekurencyjnie). – alfasin

+0

Downvoter - prosimy o komentarz! – alfasin

+0

Która książka to jest? Czy autor jest Robertem Fischerem? –

Odpowiedz

15

W Lambda Best Practices sekcji Rozdział 2, książka Fischera mówi:

O ile to możliwe, należy używać Referencyjna metoda zamiast lambda. Odnośniki metod są nie tylko krótsze i łatwiejsze do odczytania, ale użycie odwołań metod pozwoli ci bezpośrednio myśleć o metodach jako wartościach. Jest to kod trzeba akcyzy ze swoim kodzie i mózg:

x -> it.do(x) 

Jeśli naturalnie pisząc ten kod, to jeszcze nie wykonany skok do myślenia na wyższym poziomie funkcjonalnym programowanie. Gdy dokonasz takiego skoku, znacznie łatwiej będzie się komunikować i pracować ze złożonymi funkcjami, ponieważ będziesz myślał o typach, a nie wartościach.

Chociaż w większości zgadzam się z konkluzją, nie jestem pewien, czy kupuję linię rozumowania Fischera. Odnośniki do metod są często, choć nie zawsze, krótsze niż pisane lambda. W pierwszej części mówi, że referencje metod pomogą ci myśleć o metodach jako wartościach. OK, ale później mówi, że rzeczy staną się łatwiejsze, ponieważ będziesz myślał o typach, a nie wartościach. Nie jestem pewien co to znaczy.

Istnieje możliwość przerobienia przykład wyraz daje jako

it::do 

to na pewno krócej niż oryginał, ale trudno jest uogólniać z maleńkim przykładzie.

Oto moje zdanie na temat metod referencji i zapisanych lambd.

Jeśli istnieje możliwość wyboru między wyrażeniem lambda a odwołaniem do metody, to jest to , często przypadek, w którym preferowane jest odniesienie do metody. Ale nie jest to reguła twarda i szybka, i prawdopodobnie istnieją okoliczności, w których preferowane jest wyrażenie lambda. To także kwestia gustu.

Jeśli znasz wyrażenia lambda z innych języków, wyrażenia lambda w Javie będą prawdopodobnie bardziej znane niż odwołania do metod. Uważam jednak, że jest to stan tymczasowy, dopóki nie poznasz referencji metod. Gdy są bardziej znane, zalety odniesień do metod mogą przeważyć początkową nieznajomość.

Rozważmy prosty przykład uzyskanie długości ciągi:

List<String> list = ... ; 
int[] lengths1 = list.stream().mapToInt(s -> s.length()).toArray(); 
int[] lengths2 = list.stream().mapToInt(String::length).toArray(); 

w tym przypadku, wielkość wyrażenia lambda jest po prostu o tym samym jako wielkości odniesienia metody (w liczbie znaków). Ale zauważ, że odwołanie do metody zawiera więcej informacji o typie. Informuje czytelnika, że ​​typ elementu to String, co może być pomocne w zrozumieniu długiego rurociągu. Czasem jest to pomocne również dla kompilatora, jeśli nie można wywnioskować typu elementu, ponieważ czasami występuje w złożonych wyrażeniach.

Inną kwestią jest to, że użycie odnośnika do metody często zwalnia cię z odpowiedzialności za wymyślenie nazwy dla formalnego parametru, który jest po prostu przekazywany do innej metody. Nazewnictwo jest często ważne, ale formaty lambda to często "śmieciowe" nazwy, takie jak ix lub s, jak w tym przykładzie.

Odwołanie do metody jest nieco bardziej wydajne, ponieważ nie musi generować statycznej metody, która musi zostać wywołana, aby uzyskać dostęp do metody String.length(). Ale ta wydajność rzadko jest ważnym czynnikiem.

rozważyć również ten przykład, celowo pozbawiona kontekstu:

(x, y) -> x + y 

Czy to konkatenacji ciąg liczbowy lub dodatek? Jeśli numeryczne, jaki typ? Zgodnie z regułami języka, musi to być znane w czasie kompilacji, w przeciwnym razie jest to błąd. Chociaż może to być jasne dla kompilatora, czasami nie jest to zbyt jasne dla czytelnika. Zamiast tego należy rozważyć następujące odniesienia do metod:

String::concat 
Integer::sum 
Double::sum 

Używanie nazwy operacji w tym przypadku bardzo wyraźnie informuje czytelnika o tym, co jest przeznaczone.

Powiązane problemy