Java 객체 배열과 참조 교환
요약
Java에서 객체 배열이 참조를 저장하는 방식과, 배열 요소를 교환할 때 원본 변수에 어떤 영향을 미치는지 알아봅니다. static nested class 개념과 함께 정보처리기사 실기 문제를 풀어봅니다.
객체 배열 핵심 정리
| 개념 | 설명 | 예시 |
|---|---|---|
| 객체 배열 | 배열의 각 요소가 객체의 참조(주소) 를 저장 | BO[] arr = {a, b, c}; |
| 참조 교환 | 배열 요소를 교환하면 참조만 바뀜, 원본 변수는 그대로 | arr[0] = arr[2]; |
| 필드 수정 | 배열 요소를 통해 객체 필드를 수정하면 원본 객체가 변경됨 | arr[1].v = 10; |
| static nested class | 외부 클래스의 인스턴스 없이 독립적으로 사용 가능한 내부 클래스 | public static class BO |
객체 배열이란?
객체 배열 은 객체를 여러 개 담을 수 있는 배열입니다. 하지만 배열 안에 객체 자체가 들어가는 것이 아니라, 객체를 가리키는 참조(주소) 가 저장됩니다.
위 코드 실행 후 메모리 상태는 다음과 같습니다.
a와 arr[0]은 같은 객체를 가리킵니다. b와 arr[1], c와 arr[2]도 마찬가지입니다.

배열 요소 교환 (참조 교환)
배열의 요소를 교환하면, 배열 안의 참조만 바뀝니다. 원본 변수 a, b, c가 가리키는 대상은 변하지 않습니다.
교환 전후 비교
| arr[0] | arr[1] | arr[2] | |
|---|---|---|---|
| 교환 전 | a가 가리키는 객체 (v=1) | b가 가리키는 객체 (v=2) | c가 가리키는 객체 (v=3) |
| 교환 후 | c가 가리키는 객체 (v=3) | b가 가리키는 객체 (v=2) | a가 가리키는 객체 (v=1) |
교환 후 메모리 상태를 보면 차이가 명확합니다.
핵심: a는 여전히 v=1인 객체를 가리키고, c는 여전히 v=3인 객체를 가리킵니다. 바뀐 것은 배열 안의 참조뿐입니다.
배열을 통한 필드 수정
배열 요소를 통해 객체의 필드를 수정하면, 원본 객체가 실제로 변경됩니다. 배열 요소와 원본 변수가 같은 객체를 가리키고 있기 때문입니다.
교환 후 arr[1]은 b가 가리키는 객체, arr[0]은 c가 가리키는 객체입니다. 따라서 위 코드는 다음과 같습니다.
b.v가 3으로 변경됩니다. 이것은 Call by Value에서 배열 요소 수정과 같은 원리입니다. 같은 객체를 가리키는 모든 곳에서 변경이 보입니다.
static nested class
이 문제에서 BO 클래스는 Main 클래스 안에 static으로 선언되어 있습니다.
static nested class 는 외부 클래스의 인스턴스 없이 독립적으로 사용할 수 있는 내부 클래스입니다. 일반 클래스와 거의 동일하게 동작합니다.
| 특징 | 설명 |
|---|---|
| 독립적 생성 | new Main()없이 new BO(1)로 직접 생성 가능 |
| 외부 클래스 접근 | 외부 클래스(Main)의 인스턴스 멤버에 직접 접근 불가 |
| 같은 파일 안에 선언 | main 메서드에서 바로 사용할 수 있음 |
실전 예제: 전체 추적
아래 코드를 단계별로 추적해 보겠습니다.
단계별 상태 추적
| 단계 | 코드 | a.v | b.v | c.v | arr[0] | arr[1] | arr[2] |
|---|---|---|---|---|---|---|---|
| 1 | 객체 생성 | 1 | 2 | 3 | - | - | - |
| 2 | 배열 초기화 | 1 | 2 | 3 | a | b | c |
| 3 | 참조 교환 | 1 | 2 | 3 | c | b | a |
| 4 | 필드 수정 | 1 | 3 | 3 | c | b | a |
최종 출력
출력 결과: 1a3b3
정리
| 동작 | 설명 | 원본 영향 |
|---|---|---|
arr[0] = arr[2] | 배열 안의 참조를 교환 | 없음 (a, b, c 변화 없음) |
arr[1].v = 10 | 배열 요소가 가리키는 객체의 필드 수정 | 있음 (원본 객체 변경) |