2016-03-01 20 views
23

Tại sao Collections.sort(List<T>) có chữ ký:Collections.sort() tuyên bố: tại sao <? super T> hơn <T>

public static <T extends Comparable<? super T>> void sort(List<T> list) 

và không:

public static <T extends Comparable<T>> void sort(List<? extends T> list) 
  • Tôi hiểu rằng cả hai đều sẽ phục vụ cùng mục đích; vậy tại sao các nhà phát triển khung sử dụng tùy chọn đầu tiên?
  • Hoặc những khai báo này có thực sự khác nhau không?

Trả lời

19

Chữ ký được đề xuất của bạn có thể hoạt động trong Java-8. Tuy nhiên trong các phiên bản Java trước đây, suy luận kiểu không quá thông minh. Hãy xem xét rằng bạn có List<java.sql.Date>. Lưu ý rằng java.sql.Date kéo dài java.util.Date triển khai Comparable<java.util.Date>. Khi bạn biên soạn

List<java.sql.Date> list = new ArrayList<>(); 
Collections.sort(list); 

Nó hoạt động hoàn hảo trong Java-7. Tại đây, T được phỏng đoán là java.sql.Date thực tế là Comparable<java.util.Date>Comparable<? super java.sql.Date>. Tuy nhiên, hãy thử chữ ký của bạn:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {} 

List<java.sql.Date> list = new ArrayList<>(); 
sort(list); 

Ở đây T nên được suy ra là java.util.Date. Tuy nhiên, đặc tả Java 7 không cho phép suy luận như vậy. Do đó, mã này có thể được biên dịch bằng Java-8, nhưng không thành công khi được biên dịch theo Java-7:

Main.java:14: error: method sort in class Main cannot be applied to given types; 
     sort(list); 
     ^
    required: List<? extends T> 
    found: List<Date> 
    reason: inferred type does not conform to declared bound(s) 
    inferred: Date 
    bound(s): Comparable<Date> 
    where T is a type-variable: 
    T extends Comparable<T> declared in method <T>sort(List<? extends T>) 
1 error 

Suy luận kiểu được cải thiện rất nhiều trong Java-8. Riêng biệt JLS chapter 18 là dành riêng cho nó bây giờ, trong khi trong Java-7 các quy tắc were đơn giản hơn nhiều.

+1

Nhưng làm thế nào để > T max (Bộ sưu tập c) hoạt động tốt ... đây có phải là một vấn đề suy luận không? – prvn

+0

@prvn, ở đây bạn có 'So sánh ' thay vì 'So sánh ' như trong chữ ký được đề xuất của bạn. '> void sort (Danh sách list)' cũng sẽ hoạt động, nhưng thêm '? mở rộng T' là hoàn toàn không cần thiết ở đây, trong khi hợp lý trong phương thức 'max' (như' max' trả về giá trị). –

+6

Có một điểm khác. Khi bạn có loại ký tự đại diện như danh sách 'Danh sách ' bạn không thể thực hiện 'list.set (index, list.get (anotherIndex))' bên trong phương thức, do cách các loại ký tự đại diện hoạt động. Điều này có thể được phá vỡ với một phương pháp trợ giúp nội bộ bắt giữ '? mở rộng T' thành một biến kiểu khác (hoặc bằng cách sử dụng các hoạt động không được kiểm tra như các triển khai bên trong thường làm), nhưng vẫn còn, một kiểu không có ký tự đại diện sẽ rõ ràng hơn cho một danh sách sẽ được sửa đổi. – Holger

4

Chúng khác nhau vì ? super T ít hạn chế hơn T. Nó là một Lower Bounded Wildcard (các liên kết Java Tutorial nói, một phần)

Thuật ngữ List<Integer> hạn chế hơn List<? super Integer> vì cựu phù hợp với một danh sách các loại Integer chỉ, trong khi sau này phù hợp với một danh sách của bất kỳ loại đó là một siêu kiểu của Integer.

Thay Integer với T và nó có nghĩa là một Thay một java.lang.Object.

+0

nhưng tôi đang tăng flexibilty trong đối số của sort() ..using? mở rộng, – prvn

+0

Có, không ai nói rằng 'Danh sách 'giống với' List '. Phiên bản thứ hai sử dụng 'extends' và câu hỏi là nếu điều này làm cho nó bằng nhau. – JojOatXGME

+0

Tôi không nghĩ câu trả lời của bạn liên quan trực tiếp đến câu hỏi. – yuxh

9
// 0 
public static <T extends Comparable<? super T>> void sort0(List<T> list) 

// 1 
public static <T extends Comparable<T>> void sort1(List<? extends T> list) 

Những chữ ký khác nhau bởi vì họ áp đặt yêu cầu khác nhau về mối quan hệ giữa kiểu T và kiểu lập luận để Comparable trong định nghĩa của T.

Giả sử ví dụ mà bạn có lớp học này:

class A implements Comparable<Object> { ... } 

Sau đó, nếu bạn có

List<A> list = ... ; 
sort0(list); // works 
sort1(list); // fails 

Lý do sort1 thất bại là có không loại T đó là cả hai có thể so sánh với chính nó và đó là, hoặc là một siêu loại, loại của danh sách.

Nó chỉ ra rằng lớp A không đúng định dạng, vì các đối tượng là Comparable cần phải đáp ứng các yêu cầu nhất định. Đặc biệt đảo ngược so sánh nên đảo ngược dấu hiệu của kết quả. Chúng ta có thể so sánh một thể hiện của A với một số Object nhưng không phải ngược lại, do đó yêu cầu này bị vi phạm. Nhưng lưu ý rằng đây là yêu cầu của ngữ nghĩa của Comparable và không được áp đặt bởi hệ thống loại. Chỉ xem xét hệ thống kiểu, hai tờ khai sort thực sự khác nhau.

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