2011-10-26 22 views
27

Có ai biết tại sao Java 1.6 có hành vi này:tại sao Danh sách <String> .toArray() trả về Đối tượng [] chứ không phải String []? làm thế nào để làm việc xung quanh điều này?

List<String> list = ArrayList<String>(); 
String[] arr = (String[]) list.toArray(); 

Và tôi nhận được một ClassCastException, bởi vì nó sẽ trả về Object [] và không String [].

Tôi nghĩ List<T>.toArray() phải trả lại T [] - không? Có ai có câu trả lời tại sao sự bất tiện này tồn tại trong ngôn ngữ không? Và cũng có cách giải quyết vấn đề này? Làm thế nào để nhận được một chuỗi [] từ List<String> mà không lặp lại thông qua các mục?

+2

Jave doesn' t thực sự có một khái niệm 'T []'. – Gabe

+0

có thể trùng lặp của [java: (String \ [\]) List.toArray() cho ClassCastException] (http://stackoverflow.com/questions/5690351/java-stringlist-toarray-gives-classcastexception) –

Trả lời

20

Bạn cần chuyển một mảng để kiểu thời gian chạy của nó có thể được sử dụng làm gợi ý toArray. Thay vào đó, hãy thử toArray(new String[0]). Bạn cũng có thể chuyển vào một mảng có kích thước trước.

Để hiểu, xem xét những gì tẩy xoá loại sẽ phải làm gì để làm cho

new T[4] 

làm việc. Nếu Java cho phép đó, tốt nhất nó có thể làm bài tẩy xoá là

new Object[4] 

Hầu hết toArray triển khai sử dụng java.lang.reflect.Array để xây dựng một mảng đầu ra của đúng loại cho một loại gợi ý thông qua như là một Class.

+0

cảm ơn bạn Mike, Tôi đã không nhận thấy phương pháp này T [] toArray (T [] arg0) - nó trả về những gì tôi cần. – justadreamer

+9

hoặc sử dụng 'toArray (chuỗi mới [list.size()])' nếu bạn muốn tránh phân bổ mảng 0 kích thước –

+0

@ratchetfreak, cảm ơn. Đã chỉnh sửa để nói về việc định trước. –

12

Vì mảng đã có trong Java từ đầu, trong khi Generics chỉ được giới thiệu trong Java 5. Và phương pháp List.toArray() đã được giới thiệu trong Java 1.2, trước khi Generics tồn tại, và do đó nó được xác định để trở về Object[]. Rất nhiều mã hiện tại mong đợi List.toArray() để trả về Object[], vì vậy, hiện tại, mã không thể thay đổi được.

Hơn nữa, generics bị xóa khi chạy, vì vậy ArrayList thậm chí không thể xây dựng một mảng kiểu thích hợp nếu muốn.

Lỗ hổng cho phương thức này là phương pháp List.toArray(T[]), sẽ trả về cho bạn một mảng đúng loại, miễn là bạn cung cấp cho nó một mảng đúng loại để biết loại nào sẽ sử dụng.

+1

"và vì vậy nó đã được chỉ định để trả về Object []. Rất nhiều mã hiện tại mong đợi List.toArray() để trả về Object [], do đó, nó không thể thay đổi ngay bây giờ." Vô lý. Các kiểu trả về của các phương thức thu thập Java đã được thay đổi cho Generics. Điều này hoàn toàn không liên quan. Lý do thực tế là các mảng của các kiểu khác nhau ở thời gian chạy và do đó nó không thể trả về mảng của kiểu thích hợp. Điều này đúng cả trước và sau generics. – newacct

+0

Daniel, nghiêm túc? Câu hỏi này đã được hỏi về SO bao nhiêu lần? Một triệu? Và bạn đang thuyết trình tôi trả lời một câu hỏi trùng lặp? – irreputable

+0

@irreputable: Tôi đã không ngay lập tức nhìn thấy (cũng không nhớ) một bản sao chính xác khi tôi trả lời điều này ngày hôm qua. Một tìm kiếm nhanh hôm nay được bật lên [this one] (http://stackoverflow.com/questions/6173495/why-does-javas-collectione-toarray-return-an-object-rather-than-an-e) mà tôi nghĩ đủ gần. Nếu bạn bị thuyết phục rằng một câu hỏi là một bản sao, sau đó thay vì giả định đức tin xấu, tại sao không chỉ bỏ phiếu để đóng chính mình? Bạn có đủ đại diện. –

1

Lý do hai:

  1. Phương pháp này trước Generics và họ không thể thay đổi chữ ký mà không vi phạm tương thích ngược.

  2. Trong mọi trường hợp, vì List được tạo mà không có Class<T> không có cách nào để triển khai xây dựng một loại kiểu T.

+0

bạn sẽ thay đổi chữ ký thành gì? – newacct

+0

@newacct đến T [] tất nhiên. Downvoter xin giải thích. – EJP

+0

bạn có nghĩa là kiểu trả về T []? bạn sẽ nhận được một ClassCastException nếu bạn cố gắng sử dụng nó, bởi vì phương thức vẫn tạo ra một đối tượng [] – newacct

1

Giải pháp sẽ được sử dụng:

 List<String> list = new ArrayList<>(); 
     list.add("Sputnik"); 
     list.add("Explorer"); 

     //String[] str = list.toArray(); 

này chắc chắn sẽ ném một: loại không tương thích: Object [] không thể được chuyển đổi sang String [] lỗi

 Instead use: 

     String[] str = list.toArray(new String[0]); 
     or 
     String[] str = list.toArray(new String[list.size()]); 
Các vấn đề liên quan