2015-11-13 2 views
8

Я только что провел быстрый эксперимент в Eclipse.Являются ли трассировки стека менее доступными при использовании ссылок на методы против 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(); 
    } 

} 

Когда метод ссылка тест не пройден, то след начинается

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) 

Там нет ссылки назад к линии, на которой эталонный метод используется, хотя в конце следа (не показан) ссылается на линию с findFirst.

Хотя lamdba StackTrace начинается

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) 

Что правильно идентифицирует лямбда использовался на линии 26.

Является ли это особенностью компилятора Eclipse, или это общий недостаток использования ссылок методов, которые следует учитывать при выборе между ними и лямбдой?

+2

Нет, это как это происходит из Java. Они работают над улучшением опыта отслеживания стека. –

+1

Я никогда не слышал, чтобы разработчик просил более длинную трассировку стека раньше ... – Holger

ответ

4

Нет, так оно и в настоящее время реализовано.

Цитирование a paper написал Брайан Гетц о переводе лямбда-выражений:

Когда компилятор встречает лямбда-выражение, он сначала опускается (desugars) тело лямбда в метод, чей аргумент список и ответный матч типа что из лямбда-выражения

...

ссылки метод обрабатывает так же, как лямбда-выражение, за исключением того, что большинство ссылок методов не должны быть обессахаренными в новый метод; мы можем просто загрузить дескриптор константного метода для ссылочного метода и передать его метафайлу.

Единственное различие между вашими двумя stacktraces является то, что один с явной лямбда имеет эту строку добавил:

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

Это происходит потому, что лямбда был переведен javac в недавно сгенерированный метод, и вы может фактически увидеть в stacktrace, что этот новый метод был lambda$0.

С помощью ссылки на метод, нет необходимости генерировать новый метод, поскольку он непосредственно ссылается на существующий метод.

2

Нет - на самом деле вы получаете больше ясности.

Тот факт, что at com.example.StackTractTest.lambda$0(StackTractTest.java:26) линия появляется в версии лямбда напоминает вам, что лямбда создан для этого метода при использовании ссылки на метод делает ничего лишнего не создает.

Лямбда создана во время выполнения, ссылка на метод может быть построена во время компиляции.

+2

Спасибо, но я не уверен, что согласен с тем, что вы получите больше ясности.Хотя трассировка стека точно отражает то, что происходит, версия лямбда имеет практическое преимущество в определении точки использования, при которой произошла ошибка. Эта информация не выглядит доступной для ссылок на методы. Если ссылка метода появилась более одного раза в конвейере, зная, какой экземпляр вызвал исключение во время выполнения, может оказаться полезным. – henry

+2

Но это не точка, в которой произошла ошибка. Время создания - это не то же самое, что время использования для лямбды или метода. Представьте, что вы отправили лямбду в пул потоков. Ошибка произойдет намного позже, когда метод, выдающий лямбда, уже вышел. Вы в основном спрашиваете о месте размещения вместо call-site, трассировки стека информации традиционно не содержат. Это было бы похоже на запрос «где была отправлена ​​runnable, отправленная в threadpool». – the8472

 Смежные вопросы

  • Нет связанных вопросов^_^