나만의 개발 로그 | 고민 로그
배열 <깊은 복사, 얕은 복사> 본문
🧠 개념
✅ 얕은 복사 (Shallow Copy)
- 객체의 주소(참조값)만 복사
- 원본과 복사본이 같은 객체를 가리킴
- 복사본을 수정하면 원본도 함께 변경
= 연산자, .clone() (객체 배열 기준), System.arraycopy() 등
✅ 깊은 복사 (Deep Copy)
- 객체의 값을 새로운 메모리 공간에 복사
- 복사본과 원본이 완전히 독립적인 객체
- 복사본을 변경해도 원본에는 영향 없음
직접 for문 돌리기, 객체 생성 + 복사, 재귀적 복사 등
📌 얕은 복사 예제 (1차원 배열)
int[] arr = {1, 2, 3}; int[] copy = arr; // 얕은 복사
copy[0] = 99;
System.out.println(Arrays.toString(arr)); // [99, 2, 3]
→ copy와 arr이 같은 배열을 참조
📌 깊은 복사 예제 (1차원 배열)
int[] arr = {1, 2, 3}; int[] copy = arr.clone(); // 깊은 복사처럼 작동
copy[0] = 99;
System.out.println(Arrays.toString(arr)); // [1, 2, 3]
.clone()은 사실 얕은 복사 방식이지만, int[]처럼 원시 타입일 경우 값 복사이기 때문에 깊은 복사처럼 작동
⚠️ 객체 배열에서는 얕은 복사로 동작함
class Person {
String name;
Person(String name) {
this.name = name;
}
}
Person[] arr = { new Person("Alice"), new Person("Bob") };
Person[] copy = arr.clone(); // 얕은 복사
copy[0].name = "Zoe";
System.out.println(arr[0].name); // Zoe ← 원본도 바뀜!
→ copy[0], arr[0]이 같은 Person 객체를 참조하므로 얕은 복사
✅ 객체 배열의 깊은 복사 방법
Person[] arr = { new Person("Alice"), new Person("Bob") };
Person[] copy = new Person[arr.length];
for (int i = 0; i < arr.length; i++) {
copy[i] = new Person(arr[i].name); // 새로운 객체로 복사
}
copy[0].name = "Zoe"; System.out.println(arr[0].name); // Alice ← 원본은 영향 없음
🧱 2차원 배열: .clone()은 얕은 복사
int[][] arr = { {1, 2, 3}, {4, 5, 6} };
int[][] copy = arr.clone(); // 얕은 복사
copy[0][0] = 99; System.out.println(arr[0][0]); // 99 ← 원본 변경됨
→ 외부 배열만 새 객체고, 내부 배열은 동일한 주소를 공유
🔁 2차원 배열의 깊은 복사 방법
✅ 방법 1: 2중 for문
int[][] arr = { {1, 2, 3}, {4, 5, 6} };
int[][] copy = new int[arr.length][arr[0].length];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
copy[i][j] = arr[i][j];
}
}
✅ 방법 2: System.arraycopy + for
int[][] copy = new int[arr.length][];
for (int i = 0; i < arr.length; i++) {
copy[i] = new int[arr[i].length];
System.arraycopy(arr[i], 0, copy[i], 0, arr[i].length);
}
🧾 요약 정리 표
배열 종류 | 복사 방법 | 깊은 복사 여부 | 설명 |
int[] | .clone() | ✅ 깊은 복사처럼 작동 | 값 타입이라 복사됨 |
Person[] | .clone() | ❌ 얕은 복사 | 참조만 복사 |
Person[] | for + new | ✅ 깊은 복사 | 객체 생성 필요 |
int[][] | 2중 for문 | ✅ 깊은 복사 | 내부까지 값 복사 |
Person[][] | 2중 for문 | ❌ 얕은 복사 | 참조만 복사 |
Person[][] | 2중 for + new | ✅ 깊은 복사 | 객체까지 복사 필요 |
🧠 결론
- .clone()은 얕은 복사 방식이지만, 원시 타입 배열에서는 깊은 복사처럼 작동
- 참조 타입 배열이나 다차원 배열에서는 반드시 직접 복사가 필요
- 얕은 복사는 디버깅이 어려운 사이드 이펙트를 만들 수 있으니 주의
📌 정리
- 알고리즘 문제에서는 무조건 깊은 복사로 가정하고 for문 사용이 안전
- .clone()이나 System.arraycopy()는 단일 원시 배열 복사에만 권장
- 객체 배열을 복사할 땐 copy[i] = new 클래스명(...) 식으로 직접 복사
'웹 개발' 카테고리의 다른 글
Postman 테스트? NO! 테스트 코드를 활용하자! (0) | 2023.02.17 |
---|---|
Lombok @NoArgsConstructor(force = true) (1) | 2023.02.16 |
Lombok + Jackson 사용 시 boolean 필드 네이밍 주의(isIsActive...!?) (0) | 2023.02.15 |
왜 JPA에서 @DynamicInsert를 쓰면 Statement 캐싱 효율이 떨어질까? (0) | 2023.02.10 |
REST API에서 Path Variable과 Query Parameter의 차이 + JWT 기반 인증 전략 (Access Token / Refresh Token) (0) | 2023.01.12 |
Comments