2012-01-19 75 views
5

Tôi có câu hỏi về việc sử dụng Generics với bộ sưu tập.Bộ sưu tập với generics

ArrayList<Integer> al=new ArrayList<Integer>(); 

Chúng tôi biết rằng dòng trên có nghĩa là ArrayListal bị hạn chế chỉ giữ nguyên. Vì vậy, các dòng sau đưa ra một lỗi biên dịch:

al.add("wwww"); 

Nhưng tôi không hiểu những gì các dòng dưới đây có nghĩa là,

ArrayList al=new ArrayList<Integer>(); 

đâu chúng ta không cung cấp cho ArrayList<Integer> ở phía bên trái, trong khi tuyên bố. Bây giờ dòng sau không đưa ra một lỗi biên dịch:

al.add("wwww"); 

Vì vậy, nếu tôi tuyên bố như

ArrayList al=new ArrayList<Integer>(); 

đó có nghĩa là a1 thể chấp nhận bất kỳ loại?

Sự khác nhau giữa hai khai báo này là gì?

Trả lời

5

Với mã này:

ArrayList al = new ArrayList<Integer>(); 
a1.add("www"); 

trình biên dịch sẽ tạo ra một cảnh báo (mà bạn nên chú ý!) Nhưng mã sẽ chạy mà không có lỗi. Sự cố xảy ra khi trích xuất dữ liệu từ a1. Nếu bạn "biết" rằng nó chứa Integer giá trị, bạn chỉ có thể làm điều này:

Integer val = (Integer) a1.get(index); 

Nhưng khi bạn nhấn các yếu tố "www" bạn đang đi để có được một ClassCastException. Generics có nghĩa là để di chuyển các lỗi như vậy để biên dịch thời gian thay vì buộc nhà phát triển nghèo theo dõi cách giá trị String kết thúc trong danh sách mảng Integer đó.

9

Tuyên bố sau (không có loại chung) đã lỗi thời và không được dùng nữa. Bạn không nên sử dụng nó, nó chỉ biên dịch cho khả năng tương thích ngược. Các IDE hiện đại sẽ tạo ra cảnh báo ở đây. Cũng cần lưu ý rằng Java chỉ thực thi các kiểu generic ở thời gian biên dịch, vì vậy về mặt kỹ thuật, bạn có thể thêm kiểu không chính xác vào một tập hợp với một số phôi phụ. Đó là lý do tại sao tốt hơn nên ở lại với generics tất cả các thời gian và không bỏ qua chúng.

+1

... và IDE của bạn (nếu bạn đang sử dụng một tài khoản) có thể hiển thị cảnh báo cho nó. – Axel

+0

@Axel: +1. Độc lập tôi đã thêm cùng một bình luận cho câu trả lời của tôi, bạn phải tin tôi ;-). –

+0

Vì lý do nào đó, 7 người netbeans đã vô hiệu hóa các cảnh báo javac chuẩn theo mặc định. (và một sự gia tăng đáng kể trong việc nói với thực tập "sửa chữa cảnh báo loại thô của bạn.") – Affe

0

Việc kê khai thứ hai là về cơ bản giống như:

ArrayList<Object> al=new ArrayList<Object>(); 

do đó chấp nhận bất kỳ đối tượng. Nó không nên được sử dụng và có thể sử dụng để Java tương thích ngược (trước Java1.5).

0

bạn nên viết như thế này ArrayList<Integer> al=new ArrayList<Integer>(); để tránh thêm vào đối tượng danh sách của bạn với các loại khác vì bạn sẽ thấy thời gian biên dịch lỗi. Tất nhiên bạn có thể sử dụng ArrayList al=new ArrayList<Integer>(); nhưng sau đó bạn phải cẩn thận. Nói cách khác, hãy luôn sử dụng chữ cái đầu tiên: D

0

Generics được thực hiện theo kiểu xóa: thông tin loại chung chỉ xuất hiện vào thời gian biên dịch, sau đó nó được trình biên dịch xóa. Vì vậy, ArrayList al khai báo cho phép trình biên dịch chấp nhận bất kỳ loại nào. Đây là java doc về chủ đề này.

0

Loại khai báo này được phép cho tính tương thích ngược. Vì vậy, bạn có thể ví dụ vượt qua bạn danh sách chung cho phương thức từ kiểu cũ thư viện Mà chấp nhận danh sách chỉ thô:

List<Integer> list = new ArrayList<Integer>(); 
OldStyledClass.method(myArray); 

nơi phương pháp được khai báo như sau:

public static void method(List list)... 

Trong trường hợp này bạn có một số đặc biệt các phương thức tiện ích trong java.util.Collections. Vì vậy, bạn có thể chuyển đến danh sách được bảo vệ theo phương pháp này:

OldStyledClass.method(Collections.checkedList(myArray, Integer.class)); 

Nếu phương pháp sẽ cố gắng đưa vào đối tượng danh sách của bạn với một loại khác, bạn sẽ nhận được ClassCastException immediatley.

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