2015-05-21 14 views
8

tôi có ở đây một lớp Handler, mà là vụ phải xử lý Event s của một loại nhất định:Có cách nào để xác định kiểu tham số chung một cách rõ ràng trong biểu thức lambda không?

public interface Handler<E extends Event> 
{ 
    public void handle(E event); 

    @SuppressWarnings("unchecked") 
    public default Class<E> getEventType() 
    { 
     for(Method method: this.getClass().getDeclaredMethods()) 
     { 
      if(method.getName().equals("handle")) return (Class<E>)method.getParameterTypes()[0]; 
     } 
     throw new NullPointerException("Couldn't find the 'handle' method in this handler."); 
    } 
} 

Như bạn có thể thấy, nó sẽ cố gắng, theo mặc định, để có được những loại Event bằng cách quay đầu tiên loại tham số của phương thức handle() bất cứ khi nào bạn thực hiện getEventType() (ngược với Handler trả về một cách rõ ràng). Này hoạt động một cách chính xác với các thử nghiệm JUnit sau:

public static class EmptyEvent extends Event 
{ 
    public void test() { } 
} 

public static Handler<EmptyEvent> genericHandler = new Handler<EmptyEvent>() 
{ 
    @Override 
    public void handle(EmptyEvent event) 
    { 

    } 
}; 

@Test 
public void testEventGenerics() 
{ 
    //prints the name of EmptyEvent 
    System.out.println(genericHandler.getEventType()); 
} 

Intellij IDEA nói với tôi rằng tôi có thể đơn giản hóa genericHandler để một biểu thức lambda, vì vậy tôi làm điều đó:

public static class EmptyEvent extends Event 
{ 
    public void test() { } 
} 

public static Handler<EmptyEvent> genericHandler = event -> { }; 

@Test 
public void testEventGenerics() 
{ 
    //prints the name of the base Event class 
    System.out.println(genericHandler.getEventType()); 
} 

Tuy nhiên, các thử nghiệm in ra tên của Event, không phải EmptyEvent.

Vì vậy, câu hỏi của tôi là, Có cách nào để xác định rõ ràng loại tham số chung của một biểu thức lambda không?

Tôi đã cố gắng làm một cái gì đó như thế này, nhưng nó không làm bất cứ điều gì (còn nó là một lỗi)

public static Handler<EmptyEvent> genericHandler = (EmptyEvent)event -> { }; 

Trả lời

4

Có bạn có thể xác định loại của một số biểu thức lambda:

public static Handler<EmptyEvent> genericHandler = (EmptyEvent event) -> { }; 

Nói chung nó không cần thiết vì nó được ngụ ý bởi ngữ cảnh. Tuy nhiên nó thường làm cho mã dễ đọc hơn.

Xem https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27 để biết thêm chi tiết

+0

Hmm. Nó biên dịch và điều này trả lời câu hỏi, nhưng vì lý do nào đó 'genericHandler.getEventType()' vẫn trả về tên của 'Event'. Bạn có ý kiến ​​gì không? – octopod

+0

@Octopod có thể vì bạn đang dựa vào thứ tự mà các phương thức khác nhau được trả về bởi 'getDeclaredMethods', đó là một số không. – immibis

+0

@immibis ngoại trừ việc tôi khá chắc chắn rằng chỉ có một phương thức 'handle()' (cái tôi đã định nghĩa), không có ở đó? Bạn có nói rằng cũng có một 'xử lý (sự kiện)' quá? – octopod

1

Bạn đang làm cho các giả định về các lớp của đối tượng mà lambda để đánh giá, và tôi không nghĩ rằng những giả định là hợp lệ. Nó đủ để lambda ghi đè phương thức handle() từ Handler và khi chạy, phương thức handle() mất Event là đủ để ghi đè handle() từ Handler, sau khi xóa mất Event. Không nơi nào là nó đảm bảo rằng lambda phải có một phương pháp handle() có thể được introspected để nói rằng phải mất EmptyEvent.

0

Các biến sau có thể trỏ đến cùng một đối tượng!

Handler<EventA> handlerA = event -> { }; 
Handler<EventB> handlerB = event -> { }; 

Consumer<String> consumer1 = string -> {} 
Consumer<Integer> consumer2 = integer-> {} 

Bạn không thể thực sự lý do về loại thời gian chạy chính xác của biểu thức lambda; sự đảm bảo duy nhất là cơ thể lambda hoạt động trong thời gian chạy.

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.4

Các [runtime] thân phương pháp vừa thể hiện hiệu lực thi hành đánh giá cơ thể lambda

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