2013-10-02 14 views
9

Tôi đang cố gắng tạo một ImmutableMap ánh xạ các lớp thành chuỗi (lưu ý: đây là, tất nhiên, chỉ là một ví dụ!). Tuy nhiên, cái gì đó nhưSự cố khi tạo Bản đồ Không có Bản đồ với Lớp <?> làm khóa

ImmutableMap<Class<?>, String> map = ImmutableMap.of( 
    Integer.class, "Integer", 
    Date.class, "Date" 
); 

mang lại cho tôi những lỗi sau

Type mismatch: cannot convert from ImmutableMap<Class<? extends Object&Comparable<?>&Serializable>,String> to ImmutableMap<Class<?>,String> 

Lạ lùng thay nó làm việc nếu tôi thêm một dàn diễn viên để Class<?> cho bất kỳ (!) Trong những chìa khóa, ví dụ:

ImmutableMap<Class<?>, String> map = ImmutableMap.of(
    Integer.class, "Integer", 
    Date.class, "Date", 
    (Class<?>) String.class, "String", 
    long.class, "Long" 
); 

sẽ hoạt động tốt. Tôi đang bối rối bởi hành vi này: Đối với một, tại sao nó không hoạt động mà không có phôi? Tất cả đều là các lớp và nó thực sự không có gì chung hơn Class<?>, vậy tại sao nó không hoạt động? Thứ hai, tại sao một diễn viên trên bất kỳ một trong những chìa khóa làm cho nó hoạt động?

(mặt lưu ý: nếu bạn đang tự hỏi tại sao tôi thậm chí muốn làm một điều như vậy - có, đó là vì Reflection ...)

Edit: Tôi thực sự chỉ ra rằng điều này sẽ làm việc, nhưng Tôi muốn stil muốn hiểu hành vi trên

ImmutableMap<Class<?>, String> map = ImmutableMap.<Class<?>, String>builder() 
    .put(Integer.class, "Integer") 
    .put(Date.class, "Date") 
    .build(); 

Trả lời

15

Đây là cách trình biên dịch nhập thông số loại khi bạn vượt qua đối số phương pháp không nhất quán. Nếu bạn nhận thấy, phương pháp ImmutableMap.of(K, V, K, V) sử dụng cùng thông số loại K cho cả hai DateInteger. Người ta sẽ nghĩ rằng điều này sẽ thất bại khi chúng tôi đang đi qua các đối số phương pháp không nhất quán, có nghĩa là chúng tôi đang đi qua các loại khác nhau cho cùng một thông số loại K. Nhưng đáng ngạc nhiên là không.

Class<Date>Class<Integer> đang chụp mui trần cho tất cả các nội dung sau:

  • Class<? extends Object>
  • Class<? extends Serializable>
  • Class<? extends Comparable<?>>

Vì vậy, loại K được suy ra như một hỗn hợp của tất cả:

K := Class<? extends Object&Serializable&Comparable<?>> 

Đó là giá trị trả về của phương pháp này thực sự sẽ là:

ImmutableMap<Class<? extends Object&Serializable&Comparable<?>>, String> 

Tất nhiên, bạn không thể gán trực tiếp đến ImmutableMap<Class<?>, String>, vì chúng là loại không tương thích. Cũng lưu ý rằng, bạn không thể khai báo rõ ràng bản đồ của mình như trên, bởi vì bạn không thể đưa ra nhiều giới hạn cho các ký tự đại diện. Nó chỉ là làm thế nào trình biên dịch infers loại.

Đối với các loại tình huống, nơi trình biên dịch không thể suy ra một cách chính xác những lập luận kiểu như bạn yêu cầu, bạn có thể vượt qua đối số kiểu tường minh, trong khi phương pháp gọi, đó là những gì bạn đã làm trong thử cuối cùng của bạn:

ImmutableMap<Class<?>, String> map = ImmutableMap.<Class<?>, String>of( 
    Integer.class, "Integer", 
    Date.class, "Date" 
); 

này bây giờ sẽ làm việc, như trình biên dịch biết từ đối số kiểu tường minh rằng giá trị trả về sẽ là các loại - ImmutableMap<Class<?>, String>

Lạ lùng thay nó d oes làm việc nếu tôi thêm một dàn diễn viên để Class<?> cho bất kỳ (!) trong những chìa khóa

Ngay sau khi bạn gõ đúc bất kỳ yếu tố để Class<?>, vì Class<?> biểu thị gia đình tất cả tất cả các trường hợp của Class<T>, và do đó nó là loại siêu phổ biến cho tất cả các phiên bản Class. Vì vậy, đối số loại sẽ được suy ra tự động là Class<?>. Và nó sẽ hoạt động tốt.

+0

Tuyệt vời. Cảm ơn! –

+0

@ IngoBürk Bạn được chào đón :) –

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