2010-04-18 20 views
19

tôi đang gặp khó khăn tìm hiểu bài viết sau: http://www.ibm.com/developerworks/java/library/j-jtp01255.htmlgenerics java hiệp phương sai

Dưới,

Generics không hiệp biến

các bang tác giả,

Vì ln là Danh sách, thêm Float cho nó có vẻ hoàn toàn hợp pháp. Nhưng nếu ln được gán bí danh với li, thì sẽ phá vỡ lời hứa an toàn loại ẩn trong định nghĩa li - rằng đó là danh sách các số nguyên, trong đó là lý do loại chung không thể là .

Tôi không thể hiểu được phần mà nó nói "nếu ln được đặt bí danh với li". Tác giả có nghĩa là gì bằng bí danh? (Tham chiếu?). Đoạn mã trên dòng được trích dẫn dường như minh họa WHAT là bất hợp pháp trong java và không phải TẠI SAO. Nó sẽ rất hữu ích cho tôi nếu ai đó có thể giải thích bằng một ví dụ. Cảm ơn trước.

+0

IIRC, kiểu generic là không hiệp biến bởi vì họ không thể thay đổi cách mảng được thực hiện/sử dụng trong các phiên bản trước của Java (tương thích ngược), nó rung chuông với ai đó? – Rhangaun

+0

@Skeptic, Mảng là một ví dụ về việc thực hiện genervariant generics có thể trông như thế nào - nó sẽ ném các ngoại lệ thời gian chạy. Java không thể làm điều đó vì các generics bị xóa trong thời gian chạy, vì vậy nó chỉ có thể kiểm soát nó thông qua giới hạn hiệp phương sai. – Yishai

+0

@Yishai, vấn đề với mảng được thảo luận bởi Steele trong một bài thuyết trình có tên là "Phát triển một ngôn ngữ" mà tôi dường như không thể tìm thấy ngay bây giờ. – Rhangaun

Trả lời

39
List<Integer> li = new ArrayList<Integer>(); 
List<Number> ln = li; // illegal 
ln.add(new Float(3.1415)); 

Trong Java, Integer thừa hưởng từ Số (java.lang.Number), vì vậy bằng trực giác, bất cứ điều gì đó là một Integer (java.lang.Integer) cũng là một con số, nhưng những gì bài viết mà chỉ ra là với Generics nó không hoạt động theo cách đó, vì xem xét rằng ví dụ, bạn có thể kết thúc đặt một phao (là một số) vào một List<Integer>, đó là bất hợp pháp vì một phao không phải là một số nguyên.

Kết luận: Generics không phải là biến thể.

Lưu ý: Tôi khuyên bạn nên đọc Java hiệu quả (Ấn bản thứ hai) Chương 5: Generics.

+0

Cảm ơn. 8) Tôi nghĩ rằng lời giải thích không liên quan gì đến đoạn mã. Tôi ngớ ngẩn quá. – soocracy42

+0

+1 cho reco để đọc Java hiệu quả. Tôi đã viết mã trong nhiều năm, và đã chọn EJ cách đây một tháng và ngay lập tức đã học được 5 hoặc 6 chiến lược cực kỳ quan trọng. –

+0

Bài viết này cũng vô cùng hữu ích: https://www.ibm.com/developerworks/java/library/j-jtp01255/index.html –

8

Nếu bạn có thể làm một cái gì đó như thế này:

List<Float> foo; 
List<Object> bar; 

foo = new ArrayList<Float>(); 
bar = foo; 

foo.add(1.0f); 
bar.add("Hello"); 

mọi thứ sẽ đi RẤT sai. Trong thanh ví dụ này là một bí danh cho foo, và nếu bạn có thể làm điều đó bạn sẽ mất an toàn kiểu là lý do chính mà generics tồn tại.

+0

Cảm ơn rất nhiều. Tôi không chắc chắn về phần bí danh. Điều này khẳng định giả định của tôi là đúng. – soocracy42

+0

Ah! Vì vậy, bây giờ "Hello" không chỉ trong 'bar' (mà có lẽ sẽ là tốt), mà còn trong' foo'. Cuối cùng nó có ý nghĩa :) Tôi đoán sau đó tôi có thể tuyên bố một phương pháp đúc danh sách, mà sẽ phải sao chép danh sách, hm. –

-2
public class vechicle { 
void drive(){ 
} 
} 
class car extends vechicle{ 
     //Covariance 
    vechicle getObject(){ 
     return new car(); 
    } 
     //contravariance 
    car getmyObject(){ 
     return (car) new vechicle(); 
    } 
} 
+0

java.lang.ClassCastException sẽ tăng tại 'return (car) new vechicle();' – Rembo