2014-07-17 18 views
24

này thất bại trong việc biên dịch trong Java 7:Suy luận kiểu chung không hoạt động với chuỗi phương pháp?

class Map<K,V> { 
    static <K,V> Map<K,V> empty() {return null;} 
    Map<K,V> put(K k, V v) {return null;} 
    V get(K k) {return null;} 
} 

class A { 
    static void f(Map<Integer,String> m){} 
    public static void main(String[] args) { 
     f(Map.empty()); 
    } 
} 

Nó không suy ra các loại bê tông của Map được trả lại từ Map.empty():

$ javac7 A.java 
A.java:10: error: method f in class A cannot be applied to given types; 
     f(Map.empty()); 
     ^
    required: Map<Integer,String> 
    found: Map<Object,Object> 
    reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion 
1 error 

Nó biên dịch nếu bạn thay đổi cuộc gọi f để f(Map.<Integer,String>empty()); . Trong Java 8, nó hoạt động mà không cần phải sử dụng đến điều này.

Nhưng nếu bạn thay đổi cuộc gọi f thành f(Map.empty().put(1,"A").put(2,"B"));, không thể biên dịch lại một lần nữa, trên cả Java 7 và 8. Tại sao?

$ $javac7 A.java 
A.java:10: error: method f in class A cannot be applied to given types; 
     f(Map.empty().put(1,"A").put(2,"B")); 
     ^
    required: Map<Integer,String> 
    found: Map<Object,Object> 
    reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion 
1 error 

$ $javac8 A.java 
A.java:10: error: incompatible types: Map<Object,Object> cannot be converted to Map<Integer,String> 
     f(Map.empty().put(1,"A").put(2,"B")); 
            ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 
1 error 

$ $javac8 -Xdiags:verbose A.java 
A.java:10: error: method f in class A cannot be applied to given types; 
     f(Map.empty().put(1,"A").put(2,"B")); 
     ^
    required: Map<Integer,String> 
    found: Map<Object,Object> 
    reason: argument mismatch; Map<Object,Object> cannot be converted to Map<Integer,String> 
1 error 
+0

Chỉ cần chắc nó 'tĩnh Bản đồ trống() {return null;}', nó không thích thêm của bạn bất kỳ bổ sử dụng Generics anyway. –

Trả lời

24

Tại sao?

Do suy luận kiểu của các loại generics chưa được mở rộng để gọi chuỗi.

Từ java tutorial on generics type inference:

Khái niệm về những gì là một loại mục tiêu đã được mở rộng để bao gồm đối số phương pháp.

Đó là lý do tại sao mã này:

f(Map.empty()); 

biên dịch.

Nhưng mã này không bởi vì đây là một invocation xích:

f(Map.empty().put(1,"A").put(2,"B")); 

Bạn cũng có thể tìm thấy một đoạn nhỏ trong JSR-000335 Lambda Expressions for the JavaTM Programming Language Final Release for Evaluation (đặc biệt là phần D):

Có đã được một số quan tâm trong việc cho phép suy luận để "chuỗi": trong một(). b(), đi qua thông tin loại từ lời gọi của b đến lời gọi a. Điều này bổ sung thêm một chiều hướng khác cho độ phức tạp của thuật toán suy luận, vì thông tin từng phần phải truyền theo cả hai hướng; nó chỉ hoạt động khi xóa bỏ kiểu trả về của dấu() được cố định cho tất cả các instantiations (ví dụ: List). Tính năng này sẽ không phù hợp với mô hình biểu thức poly vì loại mục tiêu không thể dễ dàng bắt nguồn; nhưng có lẽ với những cải tiến bổ sung, nó có thể được thêm vào trong tương lai.

Vì vậy, có lẽ trong Java 9.

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