2011-01-25 32 views
16

Mọi người nói rằng phương pháp asList chuyển đổi mảng thành danh sách và không sao chép, vì vậy mọi thay đổi trong 'aList' sẽ phản ánh thành 'a'. Vì vậy, thêm các giá trị mới trong 'aList' là bất hợp pháp, vì mảng có kích thước cố định.Arrays.asList() nghi ngờ?

Nhưng, asList() phương thức trả về ArrayList<T>. Cách trình biên dịch phân biệt dòng 3 từ 5. Dòng 3 cho tôi ngoại lệ (UnsupportedOperationException).

 String[] a = {"a","b","c","d"};//1 
     List<String> aList = Arrays.asList(a);//2 
     aList.add("e");//3 
     List<String> b = new ArrayList<String>();//4 
     b.add("a");//5 
+5

Không quan trọng những gì 'mọi người nói'. Nó quan trọng những gì * Javadoc * nói. – EJP

Trả lời

3

Đó là ngoại lệ và không phải lỗi trình biên dịch. Nó được ném khi chương trình được chạy và không phải lúc biên dịch. Về cơ bản lớp thực tế mà Arrays.asList sẽ trả về có một số throw UnsupporteOperationException bên trong phương thức add().

Để cụ thể hơn, Arrays.asList sẽ trả lại lớp bên trong được xác định trong lớp Arrays bắt nguồn từ AbstractList và không triển khai phương thức add. Phương pháp add từ AbstractList thực sự là ném ngoại lệ.

33

Triển khai Danh sách này bạn nhận được từ Arrays.asList là chế độ xem đặc biệt trên mảng - bạn không thể thay đổi kích thước của nó.

Loại trả lại là Arrays.asList()java.util.Arrays.ArrayList thường bị nhầm lẫn với java.util.ArrayList. Arrays.ArrayList chỉ cần hiển thị mảng làm danh sách.

+3

+1 Tôi nghĩ rằng đây chính là điểm mấu chốt của câu hỏi. OP thấy rằng kiểu trả về là ArrayList, và tự hỏi tại sao nó hoạt động khác với ArrayList. Câu hỏi hoàn toàn hợp lệ. –

+0

Andreas_D, kiểu trả về của 'Arrays.asList (...)' là 'java.util.List' và không phải là' java.util.Arrays.ArrayList'. –

3

Bạn giả định rằng Arrays.asList() trả về số ArrayList, nhưng không phải như vậy. Arrays.asList() trả về việc triển khai List không xác định. Triển khai thực hiện đó chỉ cần ném một số UnsupportedOperationException vào mỗi phương thức không được hỗ trợ.

4

asList() không trả về số java.util.ArrayList, trả về java.util.Arrays$ArrayList. Lớp này thậm chí không mở rộng java.util.ArrayList, vì vậy hành vi của nó có thể (và là) hoàn toàn khác nhau.

Phương pháp add() được kế thừa từ java.util.AbstractList, theo mặc định chỉ cần ném UnsupportedOperationException.

+0

Không, asList trả về một Danh sách. Những gì bạn mô tả có thể đúng cho một thực thi Java cụ thể, nhưng không phải là bất cứ điều gì bạn có thể dựa vào. – jarnbjo

+0

@jarnbjo - Điều này đúng với cả Sun Java và GNU Classpath và có thể là bất kỳ triển khai nào khác vì đó là cách dễ nhất để thực hiện. Khi câu hỏi là về cách trình biên dịch có thể nói, tôi mặc dù một ví dụ cụ thể sẽ dễ hiểu nhất. – OrangeDog

0

asList trả về danh sách kích thước cố định để bạn không thể thêm các phần tử mới vào danh sách đó. Bởi vì danh sách nó trả về thực sự là một "khung nhìn" của mảng mà nó được tạo từ ('a' trong trường hợp của bạn), nên bạn sẽ không thể thêm các phần tử - giống như bạn không thể thêm các phần tử vào một mảng. Xem các tài liệu cho asList

9

Read again, loại Arrays.asList là:

public static <T> List<T> asList(T... a) 

trong đó nêu rõ rằng asList trả về một đối tượng mà thực hiện giao diện java.util.List, nơi nào nó nói nó sẽ trả về một thể hiện của lớp học java.util.ArrayList.

Tiếp theo, hãy chú ý rằng các tài liệu trên List.add nói:

boolean add (E e)

          Gắn các yếu tố quy định đến hết danh sách này (hoạt động không bắt buộc).

Về mặt kỹ thuật, mỗi khi bạn sử dụng biến được nhập làm Danh sách (thay vì ArrayList), bạn nên luôn cẩn thận khi phương pháp này có thể ném UnsupportedOperationException. Nếu bạn chắc chắn rằng bạn sẽ chỉ nhận được một danh sách thực hiện mà luôn luôn có ngữ nghĩa chính xác của .add(), sau đó bạn có thể bỏ qua kiểm tra có nguy cơ lỗi khi giả định của bạn không hợp lệ.

1

Mấu chốt vấn đề này là việc thực hiện List trả về bởi

List<String> aList = Arrays.asList(a); 

Nếu bạn nhìn vào mã nguồn trong Arrays bạn sẽ thấy rằng nó có chứa một nội tin lớp tĩnh ArrayList. Điều này không giống như java.util.ArrayList.

5

Manoj,

Loại Return of Arrays.List là một số thực hiện nội bộ chưa biết của giao diện Danh sách và không java.util.ArrayList, vì vậy bạn có thể gán nó chỉ để một kiểu danh sách.

Nếu bạn gán nó vào một ArrayList ví dụ nó sẽ cho bạn thời gian biên dịch lỗi "Loại không phù hợp: không thể chuyển đổi từ Danh sách đến ArrayList"

ArrayList<String> aList = Arrays.asList(a);// gives Compile time error 

Từ Javadoc "Arrays.asList Trả về một cố định (Thay đổi danh sách trả về "ghi thông qua" vào mảng.) "có nghĩa là bạn chỉ được cung cấp một khung nhìn danh sách của Array mà IMO được tạo ra trong thời gian chạy và ofcourse bạn không thể thay đổi kích thước của một mảng để bạn không thể thay đổi kích thước của "Arrays.asList".

IMO việc thực hiện nội bộ của Arrays.asList có tất cả các phương pháp thực hiện mà có thể thay đổi kích thước của Array như -

void add(E e) 
{ 
//some unknown code 
throw(java.lang.UnsupportedOperationException); 
} 

nên bất cứ khi nào bạn cố gắng để thay đổi kích thước của Array nó ném UnsupportedOperationException. Tuy nhiên nếu bạn muốn thêm một số mục mới vào ArrayList bằng cách sử dụng cú pháp như vậy, bạn có thể làm như vậy bằng cách tạo một lớp con của Arraylist (tốt hơn là bằng cách sử dụng phân lớp ẩn danh của ArrayList). Bạn có thể vượt qua các kiểu trả về của Arrays.List đến constructor của ArrayList, một cái gì đó như thế này (tức là công ArrayList (Collection c).) -

List<String> girlFriends = new java.util.ArrayList<String>(Arrays.asList("Rose", "Leena", "Kim", "Tina")); 
girlFriends.add("Sarah"); 

Bây giờ bạn có thể dễ dàng thêm vào danh sách Sarah GF của bạn bằng cách sử dụng cùng một cú pháp.

PS - Vui lòng chọn câu trả lời này hoặc câu trả lời khác làm câu trả lời của bạn vì evrything đã được giải thích. Tỷ lệ chấp nhận thấp của bạn là rất khuyến khích.

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