2017-10-29 29 views
10

Tôi đang cố gắng hiểu cách sử dụng các ký tự đại diện bị ràng buộc thấp hơn ở một số độ sâu. Tôi đang cố gắng viết một phương pháp chung là copy sao chép nội dung của một số List sang một phương thức khác. Tôi đã đưa ra chữ ký phương thức này:Trên Generics Java sử dụng thấp hơn ràng buộc:? super T

<T> void copy(List<T> dest, List<? extends T> src) 

Tôi nghĩ chữ ký này là toàn diện để giải quyết tất cả các tình huống. Tuy nhiên, tôi thấy rằng trong các lớp Java Collections chữ ký phương pháp là như thế này:

<T> void copy(List<? super T> dest, List<? extends T> src) 

Tôi không hiểu tại sao họ sử dụng List<? super T> dest thay vì chỉ List<T> dest. Có thêm sự linh hoạt nào với chữ ký của họ không?

+0

Bạn có thể bao quanh mã nội tuyến bằng dấu gạch chéo ngược để tránh HTML ăn uống thuốc generic của bạn. –

Trả lời

1

Dưới đây là một ví dụ:

Đoạn sau đi biên soạn với chữ ký <T> void copy(List<? super T> dest, List<? extends T> src) nhưng không làm việc với chữ ký <T> void copy(List<T> dest, List<? extends T> src):

YourClass obj = new YourClass(); 
List<HashMap<String,String>> lhm = new ArrayList<>(); 
List<Map<String,String>> lm = new ArrayList<>(); 
obj.<HashMap<String,String>>copy (lm,lhm); 
+0

Đoạn mã trên vượt qua biên dịch với cả chữ ký. Chỉ cần kiểm tra nó trong Eclipse. – user496934

+0

@ user496934 Lạ. Tôi cũng đã thử nghiệm điều này trên Eclipse, và nhận 'Phương thức tham số hóa > copy (Danh sách >, List >) của kiểu YourClass không phải là áp dụng cho các đối số (List >, Danh sách >) ' – Eran

+1

@ user496934 Bạn đã thực hiện cuộc gọi' obj. > copy (lm, lhm) hoặc 'obj.copy (lm, lhm);'? – Eran

5

Không có sự khác biệt thực tế mà không cần nhân chứng kiểu tường minh.

Nếu không xác định một loại nhân chứng được thực hiện bởi Eran, không có sự khác biệt về tính linh hoạt giữa hai phương pháp.

Về cơ bản, việc sử dụng ? super T qua T chỉ là một sự khác biệt về kiểu dáng, tuy nhiên nó là thực hành tốt hơn, như có thể thấy bằng cách áp dụng một số nguyên tắc mã tốt:

  • Explicit ý: ? super T một cách rõ ràng hơn cho thấy những loại dest nên dùng.
  • Modularity: bạn không cần phải xem xét các ràng buộc loại trên src ở tất cả để biết loại dest có thể mất.
  • Producer Extends, Consumer Super (PECS): thông số nhà sản xuất ("ở" bên dưới) nên sử dụng extends trong khi thông số người tiêu dùng ("ngoài") nên sử dụng từ khóa super.

Sử dụng ? super T cũng là khuyến cáo của Java tutorials (họ thậm chí sử dụng một hàm copy):

Đối với mục đích của cuộc thảo luận này, nó là hữu ích để suy nghĩ của các biến như cung cấp một trong hai chức năng:

Biến "Trong" biến
Biến "trong" phân phát dữ liệu cho mã. Hãy tưởng tượng phương thức copy với hai đối số: copy(src, dest). Đối số src cung cấp dữ liệu được sao chép, vì vậy nó là tham số "trong".

An "Out" Biến
An "ra" biến chứa dữ liệu để sử dụng ở nơi khác. Trong ví dụ copy, copy(src, dest), đối số dest chấp nhận dữ liệu, do đó, đó là tham số "ngoài".

Bạn có thể sử dụng nguyên tắc "trong" và "ngoài" khi quyết định sử dụng ký tự đại diện và loại ký tự đại diện nào phù hợp. Danh sách sau đây cung cấp các hướng dẫn để làm theo:

Hướng dẫn Wildcard:

  • An "trong" biến được định nghĩa với một ký tự đại diện bị chặn trên, bằng cách sử dụng từ khóa extends.
  • Biến "ngoài" được xác định bằng ký tự đại diện bị chặn dưới, sử dụng từ khóa super.
+0

Câu hỏi này [cũng được trả lời ở đây] (https://stackoverflow.com/questions/34985220/differences-between-copylist-super-t-dest-list-extends-t-src-and-co). Tôi nghĩ rằng ví dụ cho thấy tất cả các trường hợp mà chúng tương đương là đặc biệt thuyết phục. (Không thể đóng vai trò lừa đảo vì tiền thưởng.) – River

+0

@River: Có lẽ tốt hơn nên gắn cờ cờ này bằng cờ mod giải thích rằng đó là một bản dupe thay vì trả lời nó. – Makoto

+0

@Makoto tìm thấy bản sao sau này một chút – River

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