2012-02-21 3 views
2

일부 코드를 살펴본 결과 오브젝트에 대한 변경 사항이 실제로 해당 오브젝트 또는 해당 오브젝트의 사본에 작성되었는지 여부를 이해하고 있는지 확인하고자합니다.개체 또는 해당 개체의 복사본을 변경하고 있습니까?

for(int i = 0; i < myList.size(); i++) 
{ 
    DataObject myItem = (DataObject)myList.get(i); 
    myItem.setString("someKey", "someValue"); 
} 

myList에이 데이터 객체의 목록, 그래서 목적이 목록에서 Get() 메서드를 호출 한 후 데이터 객체에 대한 항목을 캐스팅이었다 모르겠어요 :

다음은 샘플입니다. 그러나 이것이 컴파일 될 때 어떻게 처리되는지 궁금합니다. 캐스트가 새로운 객체를 생성 한 다음 setString() 메서드가 새 객체에서 호출되고 목록의 객체에는 영향을주지 않습니까? 또는 myItem이 목록의 실제 항목을 참조하고 있습니까?

감사합니다.

답변

2

캐스팅 후에도 목록의 항목을 참조합니다. 복사본이 만들어지지 않습니다.

List는 모든 클래스가 Object을 확장하므로 모든 유형의 Object에 사용할 수 있도록 Object 클래스의 유형을 반환합니다. setString을 호출하기 위해서는 컴파일러가 어떤 종류의 객체를 호출하고 있는지 알 수 있도록 참조 유형을 좀 더 구체적으로 형변환해야합니다.

제네릭 등을 사용합니다. List 목록을 사용하여 유형을 지정하면 캐스트 할 필요가 없지만 목록 작성을 제어 할 수 없거나 어떤 유형의 객체가 목록 작성을 제어 할 수 없거나 제한 할 수없는 경우 적합하지 않을 수 있습니다.

0

제네릭을 사용하는 경우 캐스트 할 필요가 없습니다. 그렇지 않으면 어떤 유형의 개체 목록이 있는지 알 수 없기 때문에 캐스트해야합니다.

하지만 어떻게 컴파일 할 때이 처리하는 궁금 - 캐스트가 새로운 객체

컴파일러가 어떤 객체를 생성하지 않을 생성됩니다. 구문과 의미를 검사합니다. 특정 라인을 컴파일하는 동안 컴파일러는 참조가 DataObject 유형이지만, list.get()은 호환되지 않는 유형의 결과를 가져 오는 객체 유형을 반환합니다. 따라서 명시 적으로 캐스팅해야합니다.

1

캐스트는 새로운 객체를 만들지 않으며, 컴파일러에게 '이봐, 내가 뭘하는지 알지. 이건 DataObject'입니다.

실제 List 구현의 유형을 모른 채로, 우리는 당신이 얻는 것이 같은 대상인지 여부를 말할 수 없습니다. Java Collections 콜렉션 중 하나 (ArrayList, LinkedList, 등 ...)를 사용하는 경우, 동일한 오브젝트 인스턴스가됩니다. 하지만 기본 인스턴스가 아닌 복사본을 반환 할 수있는 구현 (물론 내 자신이 만든 것)을 상상할 수도 있습니다.

public class MyList<T> implements List<T> { 
    private List<T> backingList = new ArrayList<T>(); 

    //methods to fulfil List interface contract... 

    @Override 
    public T get(int index) { 
     T t = backingList.get(index); 
     return makeCopy(t); 
    } 

    private T makeCopy(T t) { 
     //make a copy of t! 
    } 
} 

는 그리고 그것은 get(int) 방법은 사본을 반환하거나하지 않을 경우 (당신이 우리에게 기본 유형을 말하지 않고) 우리가 말할 수있는, 그 때문에입니다.

+0

+1 목록에 내부적으로 어떤 작업이 수행되는지 알지 못하는 것에 대한 매우 좋은 점. 불변의 목록 요소를 사용하는 또 다른 이유입니다. – biziclop

+0

오 예, 우리는 모두 이것이 잘 작동하는 List 구현이라고 가정합니다. 그러나 get() 메서드 *는 복사본을 반환 할 수 있습니다. 그러나 그것은 매우 희박합니다. 그러나 형변환 자체는 새로운 객체를 생성하지 않습니다. 잘 했어. –

+0

좋은 지적! 필자가 언급 했어야 할 것은'myList'는 코드에서'DataObject' 유형의 객체에 대해 getList() 메소드를 호출함으로써 이전에 선언되었습니다. – Poosh

0

캐스트는 새 DataObject를 작성하지 않습니다. 캐스트는 기본 객체를 래퍼 유형으로 변환 할 때을 제외한 을 새로 작성하지 않으며 toString() 메소드를 호출하는 String에 대한 명시 적 또는 암시 적 캐스트 변환시 일반적으로 새 객체를 작성하지 않습니다.

1

그것은 모든 캐스트는 유형을 선언 무시하도록 컴파일러에게 있습니다 않습니다, 목록에있는 실제 항목을 참조하고, 당신은 객체의 실제 형식이 될 것입니다 알고. (그러나 잘못된 것이면 ClassCastException 런타임을 얻게 될 것이므로 가능하면 캐스팅을 피해야합니다. 세부 사항으로 들어가기 전에 제네릭을 사용하면 도움이 될 수 있습니다.)

이제 이런 종류의 (콜렉션의 요소 수정)은 문제없이 목록에서 작동하지만 Set s이고 Map 키의 경우 불변 오브젝트 (기본적으로 생성자가 호출 된 후에 필드가 변경 될 수없는 오브젝트)를 사용해야합니다. 그렇지 않으면 오른쪽으로 작업 할 수 있습니다 음식물. 컬렉션이 여러 스레드간에 공유되는 경우에도이 문제를 방지해야합니다.

+0

+1을 다시합니다. –

0

myList.get()은보다 일반적인 유형 (예 : Object)을 반환하도록 정의 될 수 있습니다. 참조 변수가 자체보다 더 일반적인 유형을 참조하도록 만들 수는 없습니다. 따라서 캐스트를 수행해야합니다.

DataObject myItem = (DataObject) myList.get(i); 

캐스트는 새 개체를 만들지 않습니다. 캐스트는 변수 myItem이 목록의 기존 객체를 참조하도록 만 만듭니다. 따라서 setString() 메서드는 실제 객체를 변경합니다. 따라서 동일한 개체이기 때문에 목록의 개체도 변경됩니다.

0

myList 경우과 같이, 입력 된 목록으로 선언 :

List<DataObject> myList = new ArrayList<DataObject>(); 

그런 다음 캐스트가 필요하지 않습니다. 그러나 형식이 지정되지 않은 List 인 경우 해당 get 메서드는 Object 유형의 개체를 반환합니다. 그것이 캐스트가 필요한 이유 일 수 있습니다 (선언을 보지 않고, 나는 말할 수 없습니다).

그렇다고 캐스트가 새 객체를 만들지 않는다는 것을 알고 있으므로 이미 목록에있는 객체에 대한 새로운 참조를 얻게됩니다. 즉, 수정은 myList 안에 발생합니다.

+0

변수 myList는 코드의 앞부분에있는'DataObject'에서'getList()'메소드를 호출하여 선언됩니다. 나는 아마 그것을 언급 했어야했다.하지만 get() 메소드가 Object 타입의 객체를 리턴했기 때문에 그렇게 쓰여야합니다. 감사! – Poosh

0

아마 같은 Object 일 것입니다.

new 객체가 무엇을 - 추측이다 생성하는 유일한 것은? new 키워드 어떤 사람들은 내 생각에 clone()이 (정확하게 구현 된 경우) 새로운 Object를 생성하지만, 무엇을 추측합니까? 복제 기능에는 어딘가에서 new 키워드가 있습니다!

이제는 어떤 종류의 myList을 다루는 지 모르지만 표준 Java 라이브러리 (ArrayList, LinkedList, etc)의 일부인 것으로 가정하면 동일한 객체를 얻게됩니다.

P. 배열 또한 객체라는 것을 기억하십시오!

관련 문제