2009-04-06 56 views
5

Trong mã này, tại sao mảng của tôi không được khởi tạo như tôi muốn? Là vòng lặp for-each không được thiết kế để làm điều đó, hoặc tôi chỉ không sử dụng nó một cách chính xác?Tại sao vòng lặp for-each này không hoạt động?

int[] array = new int[5]; 

    //initialise array -> Doesn't work! Array still full of 0's 
    for(int i : array) 
     i = 24; 
+0

Không phải câu hỏi khác là trùng lặp? Đây là lần đầu tiên. – masher

Trả lời

14

Vòng lặp cho mỗi lần sẽ không hoạt động đối với trường hợp này. Bạn không thể sử dụng vòng lặp for-each để khởi tạo một mảng. Mã của bạn:

int[] array = new int[5]; 
for (int i : array) { 
    i = 24; 
} 

sẽ dịch một cái gì đó như sau:

int[] array = new int[5]; 
for (int j = 0; j < array.length; j++) { 
    int i = array[j]; 
    i = 24; 
} 

Nếu đây là một mảng của các đối tượng, nó sẽ vẫn thất bại. Về cơ bản, mỗi lần gán mỗi mục trong bộ sưu tập hoặc mảng, lần lượt, đến biến mà bạn cung cấp, sau đó bạn có thể làm việc với. Biến là không phải tương đương với tham chiếu mảng. Nó chỉ là một biến.

for-each không thể được sử dụng để khởi bất kỳ mảng hoặc sưu tập, bởi vì nó vòng qua các nội dung hiện tại của mảng hoặc sưu tập, đem lại cho bạn mỗi giá trị cùng một lúc. Biến số cho mỗi đối tượng là không một proxy cho một mảng hoặc tham chiếu Bộ sưu tập. Trình biên dịch không thay thế "i" của bạn (từ "int i") bằng "array[index]".

Nếu bạn có một mảng của ngày, ví dụ, và cố gắng này, mã:

Date[] array = new Date[5]; 
for (Date d : array) { 
    d = new Date(); 
} 

sẽ được dịch sang một cái gì đó như thế này:

Date[] array = new Date[5]; 
for (int i = 0; i < array.length; i++) { 
    Date d = array[i]; 
    d = new Date(); 
} 

mà như bạn có thể nhìn thấy sẽ không khởi tạo mảng. Bạn sẽ kết thúc với một mảng chứa tất cả các giá trị rỗng.

LƯU Ý: Tôi đã lấy mã ở trên, biên dịch thành một tệp .class và sau đó sử dụng jad để dịch ngược nó. Quá trình này cung cấp cho tôi mã sau đây, được tạo ra bởi trình biên dịch Java của Sun (1.6) từ đoạn code trên:

int array[] = new int[5]; 
int ai[]; 
int k = (ai = array).length; 
for(int j = 0; j < k; j++) 
{ 
    int i = ai[j]; 
    i = 5; 
} 
+0

Trên thực tế, nó không dịch thành một vòng lặp while với một iterator? –

+0

Tôi không cố gắng cung cấp bản dịch chính xác, nhưng cảm thấy tại sao nó không hoạt động. – Eddie

+0

có ý nghĩa. Chúc mừng. – masher

3

int là một loại nguyên thủy trong hệ thống, do đó, bạn đang thực sự nhận được một bản sao của giá trị của ô trong mảng, chứ không phải là một tham chiếu đến tế bào đó trong mảng mà bạn có thể gán vào ....

Hãy để tôi thử và giải thích điều này. Nếu bạn có một mảng X, trong đó X là một lớp có các thành viên dữ liệu, bạn sẽ nhận được một tham chiếu đến một ô khác trong mỗi lần lặp và có thể thay đổi trạng thái của nó bằng cách gọi hàm trên nó (ví dụ: setValue) .

Khi bạn có ints nó là một câu chuyện khác nhau, int của bạn không phải là một tham chiếu, nó là một giá trị thực tế trên stack vì nó là một kiểu nguyên thủy, do đó, trong mỗi lần lặp, để sao chép một giá trị từ mảng vào i . Sau đó bạn cập nhật i của bạn, nhưng điều đó không có hiệu lực trên mảng.

+0

Đây không phải là lý do chính xác cho sự thất bại, tuy nhiên. Nó không liên quan gì đến int nguyên thủy. Bạn không thể sử dụng for-each để khởi tạo * bất kỳ mảng * nào, cho dù nội dung của nó có nguyên thủy hay không. – Eddie

+0

Trừ khi lớp học của bạn có setValue rõ ràng() mà bạn muốn gọi. – Uri

+0

Nếu bạn sử dụng một mảng đối tượng, mã này sẽ không khởi tạo mảng. Nó không có gì để làm với biến ở đây là nguyên thủy. – Eddie

5

i chỉ là bản sao của int tại điểm đó trong mảng, chứ không phải là tham chiếu đến nó. Vòng lặp for-each không hoạt động trong trường hợp này.

0

Làm điều này thay vì:

int[] array = new int[5]; 

// initialise array -> Will work now 
for(int i = 0 ; i< array.length ; i++) 
    array[i] = 24 ; 
+0

Tôi không muốn viết ra tất cả điều đó mỗi lần. Có vẻ như tôi không thể tránh xa nó .. :( – masher

+0

Chào mừng bạn đến với khía cạnh gõ lặp đi lặp lại của cuộc sống lập trình – euphoria83

4

Sử dụng

java.util.Arrays.fill(array, 24)

nếu bạn đang đi để được khởi tạo với cùng giá trị. Khác hơn thế, Eddie có khá nhiều điểm trong bản dịch của anh về cấu trúc cho từng phần.

+0

tốt đẹp! Tôi sẽ sử dụng lớp đó rất nhiều từ bây giờ! – masher

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