2015-11-13 5 views
8

Właśnie przeprowadziłem szybki eksperyment w Eclipse.Czy śledzenie stosu jest mniej żeglowne, gdy używa się referencji metod względem lambdas?

public class StackTractTest { 

    static class Nasty { 
    public Integer toInt() { 
     if (1 == 1) throw new RuntimeException(); 
     return 1; 
    } 
    } 

    @Test 
    public void methodReference() { 
    Stream.of(new Nasty()) 
     .map(Nasty::toInt) 
     .findFirst(); 
    } 

    @Test 
    public void lambda() { 
    Stream.of(new Nasty()) 
     .map(n -> n.toInt()) 
     .findFirst(); 
    } 

} 

Gdy test metodą odniesienie nie, ślad zaczyna

java.lang.RuntimeException 
    at com.example.StackTractTest$Nasty.toInt(StackTractTest.java:11) 
    at com.example.StackTractTest$$Lambda$1/1681433494.apply(Unknown Source) 
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) 

nie ma odniesienia do linii, w której odniesienie sposób jest stosowany, chociaż koniec śladu (nie pokazano) powraca do linii z findFirst na.

Choć StackTrace lamdba zaczyna

java.lang.RuntimeException 
    at com.example.StackTractTest$Nasty.toInt(StackTractTest.java:11) 
    at com.example.StackTractTest.lambda$0(StackTractTest.java:26) 
    at com.example.StackTractTest$$Lambda$1/1681433494.apply(Unknown Source) 
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) 

Które poprawnie identyfikuje lambda został wykorzystany na linii 26.

Czy to osobliwością kompilatora Eclipse czy jest to ogólny wadą stosowania metody referencje że należy wziąć pod uwagę przy wyborze między nimi a lambdą?

+2

Nie, to jak pochodzi z Java. Pracują nad poprawieniem doświadczenia w stosie. –

+1

Nigdy nie słyszałem, żeby programista prosił o dłuższy ślad na stosie przed ... – Holger

Odpowiedz

4

Nie, tak to obecnie jest realizowane.

Cytowanie a paper napisany przez Brian Goetz o tłumaczeniu wyrażeń lambda:

Gdy kompilator napotka wyrażenia lambda, najpierw obniża (desugars) ciało lambda do metody, której argumentem lista i powrotu typ dopasowania że wyrażenia lambda

...

metoda odniesienia są traktowane w ten sam sposób jako wyrażenia lambda, oprócz tego, że większość odnośników metoda nie muszą być odcukrzona do nowej metody; możemy po prostu załadować uchwyt metody stałej dla metody referencyjnej i przekazać ją do metafactory.

Jedyną różnicą między dwoma stacktraces jest to, że jeden z wyraźną lambda ma ten wiersz w brzmieniu:

at com.example.StackTractTest.lambda$0(StackTractTest.java:26) 

to dlatego, że lambda został przetłumaczony przez javac do nowo wytworzonej metodą, a ty może rzeczywiście zobaczyć w stosie, że ta nowa metoda była lambda$0.

W przypadku odwołania do metody nie jest konieczne generowanie nowej metody, ponieważ bezpośrednio odwołuje się do istniejącej metody.

2

Nie - w rzeczywistości uzyskasz większą przejrzystość.

Fakt, że linia at com.example.StackTractTest.lambda$0(StackTractTest.java:26) pojawi się w wersji lambda przypomina, że ​​lambda jest stworzony dla tej techniki podczas korzystania z Referencyjna metoda nie tworzy żadnych dodatków.

Wartość lambda jest tworzona w czasie wykonywania, odwołanie do metody może być konstruowane w czasie kompilacji.

+2

Dzięki, ale nie jestem pewien, zgadzam się, że masz większą jasność.Podczas gdy ślad stosu dokładnie odzwierciedla to, co się dzieje, wersja lambda ma praktyczną zaletę w identyfikacji miejsca, w którym wystąpił błąd. Informacje te nie są dostępne dla odniesień do metod. Jeśli odwołanie do metody pojawiło się więcej niż raz w potoku, wiedząc, która instancja uruchomiła wyjątek środowiska wykonawczego, może być użyteczne. – henry

+2

Ale nie w tym momencie wystąpił błąd. Czas utworzenia nie jest taki sam jak czas użycia dla uchwytu lambda lub metody. Wyobraź sobie przesłanie lambda do puli wątków. Błąd pojawi się znacznie później, gdy metoda wydawania lambda już zakończyła działanie. Zasadniczo pytasz o miejsce alokacji zamiast strony wywołania, ślady stosu informacji tradycyjnie nie zawierają. Byłoby to tak, jakby zapytać: "gdzie została przydzielona operacja przesłana do wątku". – the8472

Powiązane problemy