2015-11-13 13 views
8

Tôi vừa thực hiện một thử nghiệm nhanh trong Eclipse.Dấu vết ngăn xếp có ít điều hướng hơn khi sử dụng tham chiếu phương thức so với lambdas không?

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

} 

Khi thử nghiệm phương pháp tham chiếu không thành công, dấu vết bắt đầu

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) 

Không có tài liệu tham khảo về dòng mà trên đó các tài liệu tham khảo phương pháp được sử dụng mặc dù cuối của các dấu vết (không hiển thị) liên kết ngược lại với dòng findFirst vào.

Trong khi stacktrace lamdba bắt đầu

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) 

nào xác định một cách chính xác các lambda được sử dụng trên dòng 26.

Đây có phải là một nét đặc biệt của trình biên dịch Eclipse hoặc đây là một nhược điểm chung của việc sử dụng tài liệu tham khảo phương pháp mà nên được cân nhắc khi lựa chọn giữa chúng và lambda?

+2

Không, cách này đến từ Java. Họ làm việc để cải thiện trải nghiệm theo dõi ngăn xếp –

+1

Tôi chưa bao giờ nghe một nhà phát triển yêu cầu một dấu vết ngăn xếp lâu hơn trước đây… – Holger

Trả lời

4

Không, đây là cách nó hiện đang được triển khai.

trích dẫn a paper được viết bởi Brian Goetz về bản dịch của biểu thức lambda:

Khi trình biên dịch gặp một biểu thức lambda, nó làm giảm đầu tiên (desugars) cơ thể lambda thành một phương pháp mà luận danh sách và kiểu trả về trận đấu mà của biểu thức lambda

...

phương pháp tài liệu tham khảo được đối xử giống như biểu thức lambda, ngoại trừ rằng hầu hết tài liệu tham khảo phương pháp không cần phải được khử đường vào một phương pháp mới; chúng ta có thể chỉ cần tải một phương thức xử lý hằng số cho phương thức được tham chiếu và chuyển nó tới metafactory.

Sự khác biệt duy nhất giữa hai stacktraces của bạn là một với lambda rõ ràng có dòng này nói thêm:

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

Nó được vì lambda được dịch bởi javac vào một phương pháp mới được tạo ra, và bạn thực sự có thể thấy trong stacktrace rằng phương pháp mới này là lambda$0.

Với tham chiếu phương pháp, không cần thiết phải tạo phương thức mới vì nó trực tiếp tham chiếu đến phương thức hiện có.

2

Không - thực tế bạn sẽ rõ ràng hơn.

Thực tế là dòng at com.example.StackTractTest.lambda$0(StackTractTest.java:26) xuất hiện trong phiên bản lambda nhắc bạn rằng lambda là được tạo cho kỹ thuật này trong khi sử dụng tham chiếu phương thức không tạo thêm bất kỳ thứ gì.

Lambda được tạo tại thời gian chạy, tham chiếu phương pháp có thể được xây dựng tại thời gian biên dịch.

+2

Cảm ơn nhưng tôi không chắc tôi đồng ý rằng bạn hiểu rõ hơn.Trong khi dấu vết ngăn xếp chính xác đại diện cho những gì đang xảy ra, phiên bản lambda có lợi thế thực tế trong việc xác định điểm sử dụng mà tại đó lỗi xảy ra. Thông tin này không có sẵn để tham khảo phương thức. Nếu một tham chiếu phương thức xuất hiện nhiều hơn một lần trong một đường ống mà biết trường hợp nào đã kích hoạt một ngoại lệ thời gian chạy có thể hữu ích. – henry

+2

Nhưng đó không phải là điểm xảy ra lỗi. Thời gian tạo không giống như thời gian sử dụng cho một lambda hoặc xử lý phương pháp. Hãy tưởng tượng gửi một lambda đến một hồ bơi thread. Lỗi sẽ xảy ra sau này khi phương thức phát hành lambda đã thoát. Về cơ bản, bạn hỏi về trang web phân bổ thay vì trang web cuộc gọi, thông tin theo dõi ngăn xếp theo truyền thống không chứa. Nó sẽ giống như yêu cầu "nơi có runnable gửi đến một threadpool được phân bổ". – the8472

Các vấn đề liên quan