Nó phụ thuộc vào những gì bạn cần làm. Bạn cần sử dụng tham số kiểu giới hạn nếu bạn muốn làm điều gì đó như sau:
public <T extends Shape> void addIfPretty(List<T> shapes, T shape) {
if (shape.isPretty()) {
shapes.add(shape);
}
}
Ở đây chúng ta có a List<T> shapes
và a T shape
, do đó chúng ta có thể an toàn shapes.add(shape)
. Nếu nó đã được khai báo List<? extends Shape>
, bạn KHÔNG thể an toàn add
với nó (vì bạn có thể có a List<Square>
và a Circle
).
Vì vậy, bằng cách đặt tên cho tham số kiểu bị giới hạn, chúng ta có tùy chọn sử dụng nó ở nơi khác trong phương thức chung của chúng ta. Tất nhiên, thông tin này không phải lúc nào cũng bắt buộc, vì vậy nếu bạn không cần biết nhiều về loại (ví dụ: của bạn drawAll
), thì chỉ cần ký tự đại diện là đủ.
Ngay cả khi bạn không tham chiếu lại tham số kiểu bị giới hạn, một tham số kiểu bị giới hạn vẫn được yêu cầu nếu bạn có nhiều giới hạn. Đây là trích dẫn từ Câu hỏi thường gặp về Java Generics của Angelika Langer
Sự khác biệt giữa giới hạn ký tự đại diện và tham số kiểu bị ràng buộc là gì?
Một ký tự đại diện chỉ có thể có một giới hạn, trong khi một tham số kiểu có thể có nhiều giới hạn. Một ký tự đại diện có thể có giới hạn dưới hoặc giới hạn trên, trong khi không có cái gọi là giới hạn dưới cho tham số kiểu.
Giới hạn ký tự đại diện và giới hạn tham số kiểu thường bị nhầm lẫn, vì chúng đều được gọi là giới hạn và có một phần cú pháp tương tự. […]
Cú pháp :
type parameter bound T extends Class & Interface1 & … & InterfaceN
wildcard bound
upper bound ? extends SuperType
lower bound ? super SubType
Một ký tự đại diện chỉ có thể có một giới hạn, giới hạn dưới hoặc giới hạn trên. Danh sách các giới hạn ký tự đại diện không được phép.
Một tham số kiểu, trong các ràng buộc, có thể có một số giới hạn, nhưng không có cái gọi là giới hạn dưới cho một tham số kiểu.
Trích dẫn từ Phiên bản Java thứ 2 hiệu quả, Mục 28: Sử dụng các ký tự đại diện có giới hạn để tăng tính linh hoạt của API :
Để có tính linh hoạt tối đa, hãy sử dụng các loại ký tự đại diện trên các tham số đầu vào đại diện cho nhà sản xuất hoặc người tiêu dùng. […] PECS là viết tắt của từ sản xuất extends
, người tiêu dùng- super
[…]
Không sử dụng các loại ký tự đại diện làm loại trả về . Thay vì cung cấp thêm tính linh hoạt cho người dùng của bạn, nó sẽ buộc họ sử dụng các loại ký tự đại diện trong mã khách hàng. Được sử dụng đúng cách, các loại ký tự đại diện gần như vô hình đối với người dùng của một lớp. Chúng tạo ra các phương thức chấp nhận các tham số mà chúng nên chấp nhận và từ chối những tham số mà chúng nên loại bỏ. Nếu người dùng của lớp phải suy nghĩ về các loại ký tự đại diện, có thể có gì đó sai với API của lớp .
Áp dụng nguyên tắc PECS, bây giờ chúng ta có thể quay lại addIfPretty
ví dụ của mình và làm cho nó linh hoạt hơn bằng cách viết như sau:
public <T extends Shape> void addIfPretty(List<? super T> list, T shape) { … }
Bây giờ chúng ta có thể addIfPretty
, nói, a Circle
, để a List<Object>
. Đây rõ ràng là an toàn kiểu chữ, nhưng khai báo ban đầu của chúng tôi không đủ linh hoạt để cho phép nó.
Câu hỏi liên quan
Tóm lược
- Sử dụng các tham số / ký tự đại diện kiểu giới hạn, chúng làm tăng tính linh hoạt của API của bạn
- Nếu kiểu yêu cầu nhiều tham số, bạn không có lựa chọn nào khác ngoài việc sử dụng tham số kiểu bị giới hạn
- nếu loại yêu cầu giới hạn thấp hơn, bạn không có lựa chọn nào khác ngoài sử dụng ký tự đại diện giới hạn
- "Nhà sản xuất" có giới hạn trên, "người tiêu dùng" có tỷ lệ thấp hơn
- Không sử dụng ký tự đại diện trong các loại trả lại