2012-02-16 2 views
14

다음 루프가 참조를 제공하지 않고 개체의 복사본을 만드는 지 궁금합니다. 첫 번째 예제에서는 배열 객체를 할당하지 않지만 두 번째 예제에서는 배열 객체를 할당하기 때문에 그 이유가 있습니다. foreach 루프는 컬렉션의 요소를 반복하기 때문에Java : For-Each 루프 및 참조

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

처음에는 java와 같은 루프 구문이 있습니까? –

+0

@ChandraSekhar : [for-each loop java] (http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html). – RanRag

+0

@ChandraSekhar RanRag이 맞습니다. 그러나 이는 그 질문과 관련이 없습니다.아마도 OP가 코드를 다시 작성 했으므로 복사/붙여 넣기가 아니라 자신이 선호하는 언어로 생각했을 것입니다. –

답변

15

Java는 다른 많은 언어와 약간 다릅니다. 첫 번째 예제에있는 o은 단순히 객체에 대한 참조 일뿐입니다. 당신이 o = new MyObject()을 말할 때 o 전에 objects[index]을 참조 반면

, 그것은 입력 MyObject를 해당 객체에 대한 참조 o의 새로운 객체를 작성합니다.

즉, objects [index] 자체는 메모리에있는 다른 객체에 대한 참조 일뿐입니다. 따라서 객체 [index]를 새로운 MyObject로 설정하려면 객체 [index]가 가리키는 위치를 변경해야합니다.이 작업은 [index] 객체를 사용하여 수행 할 수 있습니다.

이미지 : (내 끔찍한 페인트 기술 : D)는

enter image description here

설명 : 이 자바 메모리 관리가 어떻게 작동하는지 대략이다. 정확하게는 아니지만, 어떤 수단 으로든, 그러나 대략적으로. A1을 참조하는 개체가 있습니다. 객체 배열에 액세스하면 시작 참조 점 (A1)부터 시작하고 X 블록 앞으로 이동합니다. 예를 들어, 인덱스 1을 참조하면 B1이 나타납니다. B1은 A2에서 객체를 찾고 있음을 알려줍니다. A2는 C2에 위치한 필드가 있음을 알려줍니다. C2는 기본 데이터 유형 인 정수입니다. 검색이 완료되었습니다.

o는 A1 또는 B1을 참조하지 않고 C1 또는 C2를 참조합니다. new ...라고 말하면, 새로운 오브젝트를 생성하고 거기에 넣을 것입니다 (예를 들어, A3 슬롯에). A1 또는 B1에는 영향을 미치지 않습니다.

나는 물건을 정리할 수 있는지 알려주세요.

+0

물론 그렇습니다. 그래서 첫 번째 예제에서, o는 C++ 포인터와 약간 비슷합니다. 즉, 변수는 그 자체가 변수이므로 값은 다른 변수의 주소입니다. 따라서 변수를 지정하면 변수가 가리키는 변수가 아닌 변수가 설정됩니다. 감사합니다. – rhughes

+0

정확히 : D C++과 달리 Java는 포인터 컨트롤 등을 많이하지 않습니다. 변수 참조는 메모리에 저장되고,'='그것들을 다시 참조합니다. 참조 할 때 새 변수를 작성할 수 없습니다. 그러나이 변수는 변경할 수 있습니다. 'o'가 이미 초기화되었고'o.x'가 필드 인 경우'o.x'가 가리키는 곳을 바꿀 수 있습니다. 그래서'o.x'를 재 할당 할 수 있습니다. –

3

첫 번째는 할당되지 않은 배열은 객체.

루프에 foreach 루프를 입력하면 컬렉션에 요소가 없으므로 크기가 6으로 초기화 된 빈 배열 일 뿐이므로 개체가 배열에 추가되지 않습니다.

또한,이 배열의 요소가 있었다하더라도 foreach 루프 그들 중 맨 위에 할당 할 것이라는 점에 유의하십시오

o = new MyObject(); 

기본적으로 oMyObject의 새로운 인스턴스를 할당 의미하지만 o 자체 밤은 배열 objects의 일부로 배열의 요소를 반복하는 데 사용되는 임시 컨테이너 일 뿐이지 만이 경우에는 아무 것도 없습니다.

+0

정말 비어 있지 않습니다. 내부에는 6 개의 null이 있습니다. 그렇지 않으면 좋은 대답입니다. +1 –

+0

은 그 안에'MyObject'의 요소가 없다는 점에서 비어 있습니다. –

+0

나는 우리가 똑같은 말을 다른 말로 생각한다고 생각한다. –

8

짧은 대답 : 그렇습니다. 계속 진행되고 있습니다.

긴 대답 : 당신이 게시 자바 foreach 루프가의 내용을 변경하지 않는 foreach 루프 안에 뭔가에 동일한 기준을 설정하면 desugared 버전에서 볼 수 있듯이

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(); 
} 

에 대한 문법 설탕입니다 정렬.

2

개체는 명시 적으로 개체 복제를 명시한 경우에만 복사됩니다 (이 개체는 복제 기능을 명시 적으로 구현합니다).

참조 및 이름을 혼동하는 것 같습니다.

첫 번째 예에서 foreach 내부 로컬 o 변수는 objects의 일부 개체가 메모리 영역을 참조합니다. o = new MyObject()을 수행하면 새로운 MyObject가 메모리의 다른 영역에서 초기화되고 o 참조가이 새로운 메모리 영역을 가리 키도록 다시 작성됩니다.

두 번째 예제에서는 objects[i] = new MyObject()을 작성하여 objects[i] 참조를 다시 작성해야하며 일부 로컬 o 변수는 다시 작성해야한다고 말합니다.

4

어떤 일이 벌어지고 있는지 명확히하기 위해 각 예제에 주석을 추가했습니다.

첫 번째 예 :

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(); 
} 

두 번째 예 : 내가 언급 할

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

java에서 키워드가 없으므로 컴파일되지 않습니다. 콜론 (:)을 삽입해야합니다. –

+0

편집하기 전에 사용자의 원본 코드를 복사하기 만 했으므로 놓쳤습니다. 즉, 그것은 내 대답의 요점을 변경하지 않습니다. –

+0

누가 와르는 왜 그들이 그것을했는지 말해야합니다. 부정적인 피드백은 개선을위한 설명을 제공하지 않으면 유용하지 않습니다. 이고르, 깊이가 없어서 당신이 -1라고 생각합니다. –

0

우선은 제로가 아닌 길이 배열은 foreach 루프

for(MyObject o in objects) 
안에 항상 mutable.And을 있다는 것입니다

각 반복에서 다음과 같이 작동합니다.

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

하지만 귀하는 다른 개체를 참조 번호 O에 할당합니다. 배열에있는 객체가 아닙니다. 단순히 다음과 같습니다.

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

그러나 원래 개체 [0]은 여전히 ​​null 개체를 가리 킵니다.

0

"new"연산자를 사용할 때마다 JVM이 새 인스턴스를 만들고 할당 연산자의 왼쪽 피연산자에 할당됩니다. 각 루프 또는 for 루프에는 문제가 없습니다. (: 개체을 MyObject O) O는 한번만 그을 MyObject가 인스턴스화되지 될 것이며, 객체 배열의 값이

O = Object[0] 
O = Object[1] 
O = Object[2] 
O = Object[3] 
O = Object[4] 
O = Object[5] 
같이 O 에서 복사를 유지할 것이다 생성 될 각 루프 대한 하여

우리는 카운터 증가에 신경을 쓸 필요가 없습니다. 각 루프의 아름다움입니다.