2010-01-06 44 views
18

Có bao giờ có sự khác biệt giữa ký tự đại diện không bị ràng buộc, ví dụ: <?> và ký tự đại diện bị ràng buộc có ràng buộc là Object, ví dụ: <? extends Object>?Ký tự đại diện chưa được gửi trong Java

Tôi nhớ lại việc đọc ở đâu đó rằng có sự khác biệt trong bản thảo ban đầu của generics, nhưng không thể tìm thấy nguồn đó nữa.

Trả lời

18

Là một điểm của bàn giao, có sự khác biệt nếu lớp/giao diện/phương thức/phương thức khai báo một giới hạn (trừ extends Object).

interface Donkey<T extends Thing> { } 

... 
    Donkey<? extends Object> foo; // FAIL 
+0

Wow! Bỏ lỡ điều đó hoàn toàn. – notnoop

+0

Hawtin == smrt. – orbfish

+2

ví dụ biên dịch trong javac 7 – irreputable

-1

Mọi thứ trong java ngoại trừ nguyên thủy mở rộng Object, vì vậy không, sẽ không có sự khác biệt. Tự động hóa cho phép sử dụng nguyên thủy để có thể nói mọi thứ trong java là một đối tượng.

4

Từ thử nghiệm có vẻ như, ví dụ: List<?>List<? extends Object> tương thích với cả hai cách và phương thức có chữ ký sử dụng một trong số đó có thể được ghi đè bằng chữ ký. ví dụ:

import java.util.List; 

class WildcardTest<T> { 
    public void foo(List<? extends T> bar) {} 
} 

class WildcardTest2 extends WildcardTest<Object> { 
    @Override 
    public void foo(List<?> bar) {super.foo(bar);} 
} 
-1

<? extends Object> là CHÍNH XÁC như <?>. Tôi xin lỗi tôi không có một tài liệu tham khảo tiện dụng, nhưng ... nó là. :)

EDIT: tất nhiên, tôi chỉ suy nghĩ từ một góc nhìn cụ thể khi tôi nói điều đó. Bỏ qua câu trả lời của tôi (đã được giảm xuống khá chính xác) và xem các câu trả lời được đánh giá cao hơn cho câu chuyện có thật.

+0

Xin chào Kevin, hãy chạm vào bạn. Cảm ơn bạn đã xem xét điều Executors2, nhiều đánh giá cao. :-) Ngoài ra, cảm thấy tự do để nhìn vào mục sửa đổi của tôi để "Một câu đố rất trung bình"; Tôi rất muốn xem câu trả lời "chính thức" là gì và liệu cách tiếp cận của tôi có được coi là "gian lận" hay không. :-P –

+0

Ồ, tôi không thể, vì dường như bài đăng của tôi đã bị xóa. –

32

Từ điểm thực tế đối với hầu hết mọi người, <? extends Object> giống với <?>, giống như mọi người đã đề xuất ở đây.

Tuy nhiên, chúng khác nhau ở hai điểm rất nhỏ và tinh tế:

  1. Các JVM (Java Virtual Machine Specification) có một đặc điểm kỹ thuật đặc biệt dành cho các ký tự đại diện vô biên, như ClassFileFormat-Java5 xác định rằng wildcard vô biên được mã hóa như * , trong khi mã hóa một ký tự đại diện bị ràng buộc đối tượng là +Ljava/lang/Object;. Thay đổi như vậy sẽ rò rỉ thông qua bất kỳ thư viện nào phân tích mã byte. Các nhà biên dịch cũng cần giải quyết vấn đề này. Từ revisions to "The class File Format"

  2. Từ quan điểm reifiablity, các điểm khác nhau. JLS 4.6 and 4.7 mã hóa List<?> làm loại có thể tái sử dụng, nhưng List<? extends Object> là loại bị xóa. Bất kỳ người viết thư viện nào thêm .isReifiable() (ví dụ: mjc lib) cần phải tính đến điều đó, để tuân thủ thuật ngữ JLS. Từ JLS 4.6 and 4.7.

+1

+1, Cảm ơn! Không biết điều đó! :) – missingfaktor

2

Đó là phức tạp ...

Đối với bất kỳ loại biến T, spec nói http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4

Mỗi loại biến ... có một ràng buộc. Nếu không có ràng buộc nào được khai báo cho một biến kiểu, thì Object được giả định.

Người ta cũng nghĩ rằng đó cũng đúng với ký tự đại diện và ? chỉ là viết tắt của ? extends Object.

Tuy nhiên, tìm kiếm thông qua thông số kỹ thuật, không có bằng chứng nào cho thấy ký tự đại diện phải có giới hạn trên (hoặc giới hạn dưới). "Không giới hạn" ? được xử lý nhất quán rõ ràng từ các ký tự đại diện bị chặn.

Chúng ta có thể suy ra từ quy tắc subtyping, mà List<?>List<? extends Object> là tuýp phụ của nhau, ví dụ, họ cơ bản cùng loại.

Tuy nhiên, đặc điểm xử lý chúng riêng biệt. Ví dụ http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7List<?> là một loại reifiable, nhưng List<? extends Object> là không, có nghĩa là

// ok 
    List<?>[] xx = {}; 
    // fail 
    List<? extends Object>[] yy = {}; 

    // ok 
    boolean b1 = (y instanceof List<?>); 
    // fail 
    boolean b2 = (y instanceof List<? extends Object>); 

Tôi không hiểu tại sao mặc dù. Có vẻ như hoàn toàn tốt khi nói một ký tự đại diện phải có giới hạn trên và giới hạn dưới, mặc định là Objectnull type.

+0

[JLS8] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1) - Ký tự đại diện? mở rộng Object tương đương với ký tự đại diện không bị chặn? – ZhongYu

+0

javac8 - cho phép 'Danh sách [] ', nhưng không phải' instanceof List ' – ZhongYu

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