2017-05-16 12 views
5

Tôi có đoạn mã sau:lambda vs lớp nặc danh

eventBus.subscribe(new EventBusListener<NavigationEvent>() { 
    @Override 
    public void onEvent(Event<NavigationEvent> event) { 
     event.getPayload(); 
    } 
}); 

eventBus.subscribe(new EventBusListener<NotificationEvent>() { 
    @Override 
    public void onEvent(Event<NotificationEvent> event) { 
     event.getPayload(); 
    } 
}); 

IntelliJ nói với tôi rằng tôi có thể thay thế những hai lớp vô danh bởi biểu thức lambda, như:

eventBus.subscribe((EventBusListener<NavigationEvent>) Event::getPayload); 
eventBus.subscribe((EventBusListener<NotificationEvent>) Event::getPayload); 

Compilation hoạt động tốt nhưng khi chạy ứng dụng bị lỗi với lỗi sau: java.lang.IllegalArgumentException: Could not resolve payload type do lớp getPayload() của lớp Event<T> gây ra.

Tôi đang thiếu gì với lamdbasgenerics?

+1

sử dụng 'Sự kiện :: getPayload' để loại rõ ràng loại – njzk2

+1

là một lưu ý phụ, đó không phải là lambdas, đó là các tham chiếu hàm. Nó sẽ không hoạt động với lambdas, vì lambdas không thể được sử dụng cho các giao diện chức năng với các kiểu generic – njzk2

+1

Có thể trùng lặp với [Lambda Expression và generic method] (http://stackoverflow.com/questions/22588518/lambda-expression-and -generic-method) – njzk2

Trả lời

6

Không có gì sai với tham chiếu phương pháp của bạn, nhưng IllegalArgumentException cũng không bị hệ thống con đó ném ra.

Có vẻ như sự cố được kết nối với nội dung eventBus.subscribe thực hiện nội bộ. Do xóa kiểu, chỉ có một phương thức subscribe(EventBusListener), không biết bạn đã vượt qua trong một EventBusListener<NavigationEvent> hoặc EventBusListener<NotificationEvent>.

Do thông báo “Không thể giải quyết loại tải trọng” cho biết, nó cố gắng tìm ra loại tải trọng thực tế, điều này ngụ ý sử dụng Reflection. Tùy chọn này chỉ hoạt động đối với có thể tái xuất hiện, tức là các loại không chung chung. Các lớp bên trong vô danh của bạn là có thể tái phân loại loại, không phải là chung chung nhưng có một lớp chung/giao diện chung có thể được kiểm tra qua getGenericSuperclass() resp. getGenericInterfaces().

Vấn đề với việc sử dụng tham chiếu phương thức hoặc biểu thức lambda trong ngữ cảnh đó là, nếu giao diện là chung, lớp thời gian chạy được tạo sẽ không được reifiable, nghĩa là bạn không thể tìm thấy thông số loại thực tế qua Reflection . Điều này giống như nếu bạn hay viết

eventBus.subscribe(Event::getPayload); 

Trừ khi có phương pháp quá tải cho phép bạn chỉ định loại tải trọng một cách rõ ràng, điều này sẽ không hoạt động với các biểu thức lambda hoặc tham chiếu phương pháp.

Tùy thuộc, cách khuôn khổ giải quyết loại nội bộ, sử dụng giao diện có thể tái chế có thể hoạt động, ví dụ:

interface NavigationEventListener extends EventBusListener<NavigationEvent> {} 
… 

eventBus.subscribe((NavigationEventListener)Event::getPayload); 

tất nhiên, điều này sẽ chỉ trả hết nếu bạn đang đi để nhanh chóng hơn một người biết lắng nghe của một loại như vậy, nếu không, bạn có thể ở lại với các lớp bên trong vô danh (trừ khi chụp của họ về this dụ là của bạn vấn đề).

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