Giải thích về nguyên tắc get-put


82

Tôi đã đọc cuốn sách của O'Reilly, nhờ đó tôi biết được nguyên tắc nhận đặt này .

  • Sử dụng extendský tự đại diện khi bạn chỉ nhận được các giá trị từ một cấu trúc.
  • Sử dụng superký tự đại diện khi bạn chỉ đặt các giá trị vào một cấu trúc.
  • Và đừng sử dụng ký tự đại diện khi cả hai bạn muốn lấy và đặt từ / đến một cấu trúc.

Các trường hợp ngoại lệ là:

  • Bạn không thể đặt bất kỳ thứ gì vào kiểu được khai báo bằng extendský tự đại diện ngoại trừ giá trị null, thuộc về mọi kiểu tham chiếu.

  • Bạn không thể lấy bất cứ thứ gì từ một kiểu được khai báo bằng superký tự đại diện ngoại trừ một giá trị của kiểu Object, đây là kiểu siêu của mọi kiểu tham chiếu.

Bất cứ ai có thể giúp tôi khám phá quy tắc này sâu hơn? Nếu có thể, hãy đặt chúng theo cách phân cấp.


4
+1: Luôn vui khi thấy ai đó tìm kiếm sự hiểu rõ về một nguyên tắc cơ bản
Mọi người.

2
@ Mọi người, tôi hiểu ý bạn là cơ bản theo nghĩa cơ bản chứ không phải là mặt lưng?
Rich Seller

Câu trả lời:


164

Hãy xem xét một nải chuối. Đây là mộtCollection<? extends Fruit> bộ sưu tập của một loại trái cây cụ thể - nhưng bạn không biết (từ tuyên bố đó) loại trái cây đó là một bộ sưu tập. Bạn có thể lấy một món đồ từ nó và biết chắc chắn nó sẽ là trái cây, nhưng bạn không thể thêm vào nó - bạn có thể đang cố thêm một quả táo vào một nải chuối, điều này chắc chắn sẽ sai. Bạn có thể thêm nullvào nó, vì đó sẽ là giá trị hợp lệ cho bất kỳ loại trái cây nào.

Bây giờ hãy xem xét một quả nỏ. Đây là một Collection<? super Banana>tập hợp của một số loại "lớn hơn"Banana (ví dụ: Collection<Fruit>hoặc Collection<TropicalFruit>). Bạn chắc chắn có thể thêm một quả chuối vào món này, nhưng nếu bạn lấy một món đồ từ bát, bạn không biết mình sẽ nhận được gì - nó có thể không phải là một quả chuối. Tất cả những gì bạn biết chắc chắn là nó sẽ hợp lệ (có thể null)Object tham chiếu .

(Nói chung, đối với các câu hỏi chung về Java, Câu hỏi thường gặp Java Generics là một tài nguyên tuyệt vời chứa câu trả lời cho hầu hết mọi thứ liên quan đến generics mà bạn có thể sẽ ném vào nó.)


nhưng trong khi lấy một quả từ Bộ sưu tập <? expand Fruits>, bạn có thể nhận được bất kỳ quả nào không phải chuối. tương tự, trong khi đặt một trái cây vào nó, bạn có thể thêm bất kỳ thứ gì có thể không thuộc về trái chuối
JavaResp

6
Java sẽ ngăn bạn thêm bất kỳ thứ gì khác ngoài null vào a Collection<? extends Fruit>vì lý do chính xác đó và bạn phải truyền kết quả tìm nạp một mục một cách rõ ràng, vì những lý do chính xác đó.
Jon Skeet

@JonSkeet Đây có thể là một câu hỏi ngu ngốc, nhưng trong những trường hợp nào thì sẽ hữu ích khi không có "quyền truy cập" vào cả hai phương thức add () và get ()? Ý tôi là, để lấy () một số đối tượng ra khỏi danh sách, bạn phải thêm nó vào trước, phải không? Và ngược lại, tại sao bạn sẽ thêm nó nếu bạn không thể lấy nó sau đó?
Timmos

7
@Timmos: Chỉ vì thứ gì đó phải có thể thêm giá trị không có nghĩa là tất cả mã cần phải có. Ví dụ, để hiển thị danh sách tên người, tôi có thể chỉ cần một Collection<? extends Person>(hoặc nhiều hơn có thể chỉ là một Iterable<? extends Person>, nhưng ...). Mã tạo bộ sưu tập đó cũng có thể cần nó là a Collection<Employee>, nhưng mã tiêu thụ thì không.
Jon Skeet

5
@Timmos: Trong trường hợp này, bạn sẽ phải nói chính xác ý của bạn về "nó" ... nhưng đúng vậy, các quy tắc của Java generics được thiết kế để cung cấp sự an toàn cho kiểu.
Jon Skeet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.