2012-02-16 43 views
14

Tôi tự hỏi nếu vòng lặp sau tạo ra một bản sao của đối tượng, thay vì cho tôi một tham chiếu đến nó. Lý do là, vì ví dụ đầu tiên không phân bổ các đối tượng mảng của tôi, nhưng ví dụ thứ hai thì không.Java: Đối với mỗi vòng lặp và tham chiếu

MyObject objects[] = new MyObject[6]; 
for (MyObject o: objects) { 

    o = new MyObject(); 
} 

MyObject objects[] = new MyObject[6]; 
for(int i = 0; i < objects.length; i++) { 

    objects[i] = new MyObject(); 
} 
+0

Có cú pháp vòng lặp nào giống như cú pháp đầu tiên có trong java không? –

+0

@ChandraSekhar: [cho mỗi vòng lặp java] (http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html). – RanRag

+0

@ChandraSekhar RanRag là đúng. Tuy nhiên, điều đó không liên quan đến câu hỏi.Có lẽ OP chỉ viết lại mã của anh ta, không sao chép/dán và do đó suy nghĩ bằng ngôn ngữ ưa thích của anh ấy. –

Trả lời

15

Java hoạt động hơi khác một chút so với nhiều ngôn ngữ khác. Những gì o là trong ví dụ đầu tiên chỉ đơn giản là một tham chiếu đến đối tượng.

Khi bạn nói o = new MyObject(), nó tạo đối tượng mới loại MyObject và tham chiếu o cho đối tượng đó, trong khi trước khi o tham chiếu objects[index].

Tức là, các đối tượng [index] chính nó chỉ là một tham chiếu đến một đối tượng khác trong bộ nhớ. Vì vậy, để thiết lập các đối tượng [index] thành MyObject mới, bạn cần phải thay đổi nơi các đối tượng [index] trỏ tới, chỉ có thể thực hiện được bằng cách sử dụng các đối tượng [index].

hình ảnh: (kỹ năng sơn khủng khiếp của tôi: D)

enter image description here

Giải thích: Đây là khoảng cách quản lý bộ nhớ Java hoạt động. Không chính xác, bằng bất kỳ phương tiện nào, nhưng gần như. Bạn có các đối tượng, tham chiếu đến A1. Khi bạn truy cập mảng đối tượng, bạn bắt đầu từ điểm tham chiếu bắt đầu (A1) và di chuyển về phía trước khối X. Ví dụ, tham chiếu chỉ mục 1 sẽ đưa bạn đến B1. B1 sau đó cho bạn biết rằng bạn đang tìm đối tượng tại A2. A2 cho bạn biết rằng nó có một trường nằm ở C2. C2 là một số nguyên, một kiểu dữ liệu cơ bản. Việc tìm kiếm được thực hiện.

o không tham chiếu A1 hoặc B1, nhưng C1 hoặc C2. Khi bạn nói new ..., nó sẽ tạo một đối tượng mới và đặt o ở đó (ví dụ, trong vùng A3). Nó sẽ không ảnh hưởng đến A1 hoặc B1.

Hãy cho tôi biết nếu tôi có thể xóa mọi thứ một chút.

+0

Chắc chắn, điều đó làm cho sence. Vì vậy, trong ví dụ đầu tiên, o là một chút giống như một con trỏ C++, trong đó nó là một biến của chính nó, và do đó giá trị của nó là địa chỉ của một biến khác. Vì vậy, khi gán bất cứ điều gì cho nó, biến, thay vì những gì nó trỏ đến, được thiết lập. Cảm ơn! – rhughes

+0

Chính xác: D Không giống như C++, Java không có nhiều cách điều khiển con trỏ và như vậy. Các biến tham chiếu các vị trí trong bộ nhớ và '=' tham chiếu lại chúng. Bạn không thể tạo biến mới mà bạn đã tham chiếu. Tuy nhiên, bạn có thể thay đổi biến này. Nếu 'o' đã được khởi tạo và' o.x' là một trường, bạn có thể thay đổi vị trí 'o.x' points, do đó gán lại' o.x'. –

3

Thứ nhất không phân bổ đối tượng mảng của bạn vì các vòng lặp foreach lặp qua các phần tử trong bộ sưu tập.

Khi bạn nhập vào đó foreach vòng lặp bạn không có bất kỳ phần tử nào trong bộ sưu tập của mình, nó chỉ là một mảng trống được khởi tạo thành kích thước 6, vì vậy sẽ không có đối tượng nào được thêm vào mảng của bạn.

Ngoài ra, lưu ý rằng ngay cả khi bạn đã có các yếu tố trong mảng các foreach vòng lặp sẽ không được chuyển nhượng trên đầu trang của họ:

o = new MyObject(); 

về cơ bản có nghĩa là gán cho o một trường hợp mới của MyObject, nhưng o tự isnt một phần của mảng objects nó chỉ là một thùng chứa tạm thời được sử dụng để lặp qua các phần tử của mảng, nhưng trong trường hợp này, không có.

+0

Nó không thực sự trống rỗng, nó chỉ có 6 null bên trong. Nếu không, câu trả lời tốt. +1 –

+0

trống theo nghĩa là không có phần tử 'MyObject' bên trong nó. –

+0

Tôi nghĩ rằng chúng tôi đang nói cùng một điều trong các từ khác nhau. –

8

câu trả lời ngắn: có, có điều gì đó giống như bản sao đang diễn ra.

Các câu trả lời dài: Vòng lặp Java foreach bạn đăng là cú pháp đường cho

MyObject objects[] = new MyObject[6]; 

Iterator<MyObject> it = objects.iterator(); 
while (it.hasNext()) { 
    MyObject o = it.next(); 
    // The previous three lines were from the foreach loop 

    // Your code inside the foreach loop 
    o = new MyObject(); 
} 

Như phiên bản chương trình khử đường, thiết lập một tham chiếu tương đương với một cái gì đó bên trong một vòng lặp foreach không thay đổi các nội dung của mảng.

2

Đối tượng chỉ được "sao chép" khi bạn nói rõ bạn muốn sao chép đối tượng (và đối tượng này thực hiện rõ ràng tính năng nhân bản).

Bạn có vẻ nhầm lẫn giữa các tham chiếu và tên.

Trong ví dụ đầu tiên, bên trong một biến, địa phương o biến đề cập đến khu vực bộ nhớ một số đối tượng từ objects được lưu trữ. Khi bạn đang thực hiện o = new MyObject(), MyObject mới được khởi tạo trong một số vùng khác của bộ nhớ, và sau đó tham chiếu o được viết lại để trỏ vào khu vực bộ nhớ mới này.

Trong ví dụ thứ hai, bằng cách viết objects[i] = new MyObject(), bạn đang nói rằng tài liệu tham khảo objects[i] nên được viết lại, chứ không phải một số biến số o cục bộ.

4

Tôi đã thêm nhận xét vào từng ví dụ để làm rõ những gì đang diễn ra.

dụ đầu tiên:

MyObject objects[] = new MyObject[6]; 
for(MyObject o: objects) { 

    // Construct a new object of type MyObject and assign a reference to it into 
    // the iteration variable o. This has no lasting effect, because the foreach 
    // loop will automatically assign the next value into the iteration variable 
    // in the the next iteration. 
    o = new MyObject(); 
} 

ví dụ thứ hai:

MyObject objects[] = new MyObject[6]; 
for(int i = 0; i < objects.length; i++) { 

    // Construct a new object of type MyObject and store a reference to it into the 
    // i-th slot in array objects[]: 
    objects[i] = new MyObject(); 
} 
+0

Nó sẽ không biên dịch ở tất cả, như trong không phải là một từ khóa trong java, Bạn nên đặt dấu hai chấm (:) ở đó. –

+0

Tôi vừa sao chép mã gốc của người dùng trước khi nó được chỉnh sửa và tôi đã bỏ lỡ nó. Điều đó nói rằng, nó không thay đổi quan điểm của câu trả lời của tôi. –

+0

Ai -1 muốn Igor nên nói lý do tại sao họ đã làm điều đó. Phản hồi tiêu cực không được sử dụng nếu bạn không đưa ra lời giải thích cho các cải tiến. Igor, tôi nghi ngờ bạn là -1'd do thiếu chiều sâu. –

0

Điều đầu tiên tôi muốn nói là phi zero mảng chiều dài luôn mutable.And bên trong vòng lặp foreach

for(MyObject o in objects) 

những gì nó làm là trong mỗi lần lặp nó hoạt động như sau.

o = objects[0] // first iteration 
o = objects[1] // 2nd iteration 

Nhưng trong trường hợp bạn gán một đối tượng khác cho tham chiếu o. Không phải đối tượng trong mảng.Its đơn giản như sau.

ObjeMyObject objects[] = new MyObject[6]; 
MyObject o = Object[0]; 
0 = new MyObject(); 

Nhưng đối tượng gốc của bạn [0] vẫn trỏ đến đối tượng rỗng.

0

Mỗi khi bạn sử dụng toán tử JVM "mới" sẽ tạo một phiên bản mới và nó sẽ được gán cho toán hạng bên trái của toán tử gán. không quan trọng đối với mỗi vòng lặp hoặc vòng lặp. Trong mỗi vòng lặp for (MyObject O: Object) O sẽ được tạo ra một lần duy nhất mà sẽ được MyObject nó sẽ không được khởi tạo và các giá trị từ mảng Object sẽ được giữ sao chép trong thời gian O như

O = Object[0] 
O = Object[1] 
O = Object[2] 
O = Object[3] 
O = Object[4] 
O = Object[5] 

Chúng tôi không cần phải quan tâm đến việc tăng bộ đếm, đó là vẻ đẹp của mỗi vòng lặp.

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