Sự khác biệt giữa <?> Và <là gì? mở rộng Đối tượng> trong Java Generics?


95

Tôi đã thấy ký tự đại diện được sử dụng trước đây để có nghĩa là bất kỳ đối tượng nào - nhưng gần đây đã thấy việc sử dụng:

<? extends Object>

Vì tất cả các đối tượng đều mở rộng Đối tượng, hai cách sử dụng này có đồng nghĩa với nhau không?


2
Đó là một thứ tương tự. Xem stackoverflow.com/questions/2274720/…
Dan

3
@Dan Nếu bạn tìm kiếm "? Expand Object" trong câu hỏi đó, bạn không tìm thấy gì cả. Tôi đang đọc qua các câu trả lời để xem liệu tôi có thể suy luận được gì không nhưng tôi không nghĩ đây là nó. Cụ thể, nó không nói về generic.
orbfish

@Dan - Đó là một câu hỏi khác. Tôi đã từng thấy câu hỏi này trước đây và tôi nhớ ít nhất có đề cập đến một sự khác biệt nhỏ. Hãy để tôi xem nếu tôi có thể tìm thấy nó ..
Paul Bellora

Nó cũng không phải là cái này nếu bạn tìm thấy nó: stackoverflow.com/questions/678822/…
orbfish

1
Sau đây là: bản sao có thể có của các ký tự đại diện Không bị ràng buộc trong Java (Có câu trả lời không chính xác của Kevin Bourrillion không ít.)
Paul Bellora

Câu trả lời:


104

<?><? extends Object>đồng nghĩa, như bạn mong đợi.

Có một vài trường hợp với thuốc generic extends Objectkhông thực sự dư thừa. Ví dụ, <T extends Object & Foo>sẽ gây ra Tđể trở thành Objectdưới tẩy xoá, trong khi với <T extends Foo>nó sẽ trở thành Foodưới tẩy xoá. (Điều này có thể thành vấn đề nếu bạn đang cố gắng duy trì khả năng tương thích với API pre-generics đã được sử dụng Object.)

Nguồn: http://download.oracle.com/javase/tutorial/extra/generics/convert.html ; nó giải thích tại sao java.util.Collectionslớp của JDK có một phương thức với chữ ký này:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll
)

4
Tôi không rõ ví dụ liên quan như thế nào? (vì nó không sử dụng <?> cũng không phải <?
expand

27
@orbfish: Nó chỉ liên quan trong mà tôi nghĩ bạn sẽ tìm thấy nó thú vị, vì nó là một ví dụ nơi extends Objectthực sự có ý nghĩa. Nếu tôi đã nhầm, thì tôi xin lỗi. Hy vọng rằng nó sẽ quan tâm đến những người khác khi xem câu hỏi của bạn, ít nhất.
ruakh

@ruakh - Quan tâm đến các ký tự đại diện có giới hạn hơn là các tham số kiểu, nhưng, ít nhất, bạn đã trả lời.
orbfish

1
Bạn nên nói điều đó trong bài viết ban đầu của bạn. Bằng cách đó, câu trả lời của anh ấy có thể phù hợp hơn với bạn.
liltitus27

19

Mặc dù <?>được coi là một phím tắt cho <? extend object>, có một sự khác biệt nhỏ giữa hai. <?>là có thể tái sử dụng trong khi <? extend object>thì không. Lý do họ làm như vậy là để phân biệt loại có thể tái sử dụng dễ dàng hơn. Bất cứ điều gì giống như <? extends something>, <T>,<Integer> là nonreifiable.

Ví dụ, mã này sẽ hoạt động

List aList = new ArrayList<>();
boolean instanceTest = aList instanceof List<?>;

nhưng điều này gây ra lỗi

List aList = new ArrayList<>();
boolean instancetest = aList instanceof List<? extends Object>;

để biết thêm thông tin, hãy đọc các bộ sưu tập và tổng thể Java của Maurice Naftalin


Làm thế nào để Danh sách <?> Có thể xác định lại được nếu trình biên dịch sẽ dịch nó thành Danh sách <Đối tượng> để thông tin về kiểu của là gì? bị mất?
Trismegistos

Điều tôi tin rằng <?> Được thiết kế nhiều hơn để tương thích ngược với các API cũ. để phân biệt với <Object> và <? Mở rộng Đối tượng> là mã đăng Java 5.
Dennis C

9

<?>là cách viết tắt của <? extends Object>. Bạn có thể đọc liên kết chia sẻ bên dưới để biết thêm chi tiết.


<?>

"?"biểu thị bất kỳ loại không xác định nào, Nó có thể đại diện cho bất kỳ Loại nào trong mã cho. Sử dụng ký tự đại diện này nếu bạn không chắc chắn về Loại.

ArrayList<?> unknownList = new ArrayList<Number>(); //can accept of type Number
unknownList = new ArrayList<Float>(); //Float is of type Number

Lưu ý: <?> có nghĩa là bất cứ điều gì. Vì vậy, nó có thể chấp nhận Loại không được kế thừa từ Objectlớp.

<? extends Object>

<? extends Object>nghĩa là bạn có thể chuyển một Đối tượng hoặc một lớp con mở rộng Objectlớp.

ArrayList<? extends Number> numberList = new ArrayList<Number>(); //Number of subclass
numberList = new ArrayList<Integer>(); //Integer extends Number
numberList = new ArrayList<Float>(); // Float extends Number 

nhập mô tả hình ảnh ở đây

T - được sử dụng để biểu thị loại
E - được sử dụng để biểu thị phần tử
K - khóa
V - giá trị
N - cho số
Tham khảo:

nhập mô tả hình ảnh ở đây


"Vì vậy, nó có thể chấp nhận Kiểu không được kế thừa từ lớp Đối tượng", nhưng tất cả các lớp Java đều được kế thừa hoặc kế thừa ngầm định từ Objectlớp.
hackjutsu
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.