inflearn logo
강의

講義

知識共有

基礎タンタン!ひどく起動するJava - Part 2: OOPとJVM

[実習] MyStringにコピーコンストラクタ追加

[실습] MyString에 복사 생성자 추가

38

sjn0125

投稿した質問数 3

0

import java.lang.reflect.Field;

class MyString {
    private byte[] sdata = null;

    MyString(MyString s) {
        this.sdata = s.sdata;
    }

    // 생성자 1: 문자열을 받을 때
    MyString(String param) {
        this.setString(param);
    }

    // 생성자 2: 정수를 받을 때
    MyString(int param) {
        setString(String.format("%d", param));
    }

    // 데이터를 문자열로 반환 (null 체크 포함)
    public String getString() {
        if (sdata == null || sdata.length <= 0) {
            return "(null)";
        }
        return new String(sdata);
    }

    // 데이터를 안전하게 복사해서 저장 (Deep Copy)
    public void setString(String param) {
        sdata = param.getBytes();
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        MyString src = new MyString("Hello");
        MyString dst = new MyString(src);

        Field field = MyString.class.getDeclaredField("sdata");
        field.setAccessible(true);

        byte[] srcSdata = (byte[]) field.get(src);
        byte[] dstSdata = (byte[]) field.get(dst);

        System.out.println("src.sdata 주소: " + System.identityHashCode(srcSdata));
        System.out.println("dst.sdata 주소: " + System.identityHashCode(dstSdata));
        // 둘이 같은 숫자 → 같은 배열 가리킴 (얕은 복사 증명!)

        src.setString("world");

        byte[] srcSdata2 = (byte[]) field.get(src);
        byte[] dstSdata2 = (byte[]) field.get(dst);

        System.out.println("--- setString 후 ---");
        System.out.println("src.sdata 주소: " + System.identityHashCode(srcSdata2));
        System.out.println("dst.sdata 주소: " + System.identityHashCode(dstSdata2));
        // src는 새 주소, dst는 그대로 → 분리됨 확인!
    }
}

 

java 객체지향 jvm data-structure

回答 1

0

communityai8509

안녕하세요, 인프런 AI 인턴입니다. sjn0125님!

질문해주신 내용을 바탕으로 Java에서의 얕은 복사와 깊은 복사 과정에서 기본적으로 발생할 수 있는 상황들을 정리해보겠습니다.

얕은 복사와 깊은 복사

  • 얕은 복사(Shallow Copy): 객체의 참조 주소만을 복사합니다. 그래서 복사된 두 객체가 같은 참조를 공유하고, 하나가 변하면 다른 하나도 영향을 받습니다.
  • 깊은 복사(Deep Copy): 객체를 완전히 복제합니다. 즉, 원본과 복제된 객체가 서로 독립적인 메모리를 가집니다.

코드 분석

  1. MyString 생성자:

    • MyString(MyString s): 현재 얕은 복사가 일어나는 코드로 보입니다. s.sdata의 참조를 복사하므로 두 객체가 같은 배열을 공유하게 됩니다.
  2. setString 메서드:

    • 이 메서드에서 getBytes()를 통해 새로운 바이트 배열을 생성하여 sdata에 할당합니다.
    • 이로 인해 srcsdata가 새로운 배열을 가리키게 되고, 얕은 복사를 통해 dstsrc가 같은 배열을 가리키는 상황은 사라지게 됩니다.
  3. 메모리 주소 확인:

    • 코드를 실행한 결과, srcdstsdata가 초기에는 같은 배열을 가리키게 되지만, setString을 호출한 후에는 다른 배열을 가리키게 됩니다.

결론과 추가 설명

  • setString에 의해 원래 의도했던 얕은 복사 상황이 무효화됩니다. setString이 새로운 배열을 생성하여 할당하기 때문에 srcdstsdata가 나중에 분리되는 것입니다.
  • 이러한 점을 방지하려면, MyString 생성자에서 깊은 복사를 수행하여 s.sdata의 복제본을 this.sdata에 할당해야 합니다. 이렇게 하면, setString을 호출하기 전부터 두 객체의 sdata가 독립적으로 존재할 수 있습니다.

유사한 질문에 대한 해결 방법이 포함된 참고 링크를 통해 깊이 있는 정보를 얻으실 수 있습니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

compareTo를 사용하는 이유가 뭔가요?

0

44

1

안녕하세요~ 회수라는 의미에 대해서 질문합니다.

0

71

1

equals의 재정의(overriding)에 대해서

0

80

2

TestEx 객체 생성 시 생성자 호출 질문

0

61

2

[MyString 실습 인스턴스 중복 생성 문의] MyString.setString(String param)

0

100

2

주소록 실습 3단계에서 막혔어서 조언을 구하려고 질문 드립니다.

0

84

2

해시 알고리즘 관련으로 질문이 있습니다.

0

73

2

21분 경 Old generation의 GC 설명 질문입니다.

0

101

3

임시 객체의 첫 번째 상황에 대한 질문

0

70

2

String 객체가 하나 더 생성되는 이유가 궁금합니다

0

188

3

하위 클래스와 상위 클래스의 생성자 순서

0

103

2

GC의 age와 관련하여 질문 있습니다.

0

97

2

Object Header 의 Klass word (39강 36:00)

0

115

2

method area는 이름이 class area가 아니고 왜 method aread인지 궁금합니다.

0

138

2

교안 p.305 'throw 필수' 질문

0

81

1

Metaspace에 대한 질문

0

257

2

clone() 메서드를 재정의함으로써 Deep copy로 구현한다로 이해하면 될까요?

0

120

2

MyListEx 질문드립니다.

1

136

1

part3 강의 개강

0

197

2

문자열 비교 강좌에서 문자열 선언 방법 간에 hashCode() 값 관련한 질문입니다.

0

222

2

상속과 오지랖의 콜라보 예제에서 clone() 메서드에 대한 문의드립니다.

1

182

2

보이지 않는 임시 객체의 자막 수정 요청

0

115

2

스레드 관련해서 질문이 있습니다.

0

202

1

metaspace 관련 문의드립니다.

0

198

2