Java 객체 배열과 참조 교환
선수학습(1개)
요약
Java에서 객체 배열이 참조를 저장하는 방식과, 배열 요소를 교환할 때 원본 변수에 어떤 영향을 미치는지 알아봅니다. static nested class 개념과 함께 정보처리기사 실기 문제를 풀어봅니다.
객체 배열 핵심 정리
| 개념 | 설명 | 예시 |
|---|---|---|
| 객체 배열 | 배열의 각 요소가 객체의 참조(주소) 를 저장 | BO[] arr = {a, b, c}; |
| 참조 교환 | 배열 요소를 교환하면 참조만 바뀜, 원본 변수는 그대로 | arr[0] = arr[2]; |
| 필드 수정 | 배열 요소를 통해 객체 필드를 수정하면 원본 객체가 변경됨 | arr[1].v = 10; |
| static nested class | 외부 클래스의 인스턴스 없이 독립적으로 사용 가능한 내부 클래스 | public static class BO |
먼저 알아야 할 것: 변수에 저장되는 것 쌩기초
객체 배열을 이해하려면, Java에서 변수에 값을 대입(=)할 때 무엇이 저장되는지 알아야 합니다.
| 종류 | 변수에 저장되는 것 | 대입 시 |
|---|---|---|
기본형 (int, double 등) | 값 자체 | 값이 복사됨 |
| 참조형 (객체, 배열) | 객체의 주소 | 주소가 복사됨 |
a에는 BO 객체가 통째로 들어있는 것이 아닙니다. a에는 BO 객체가 있는 주소가 저장되어 있습니다. 이것이 이 페이지의 모든 내용을 이해하는 핵심입니다.
자세한 설명은 기본형 vs 참조형 페이지를 참고하세요.
객체 배열이란? 쌩기초
객체 배열 은 객체를 여러 개 담을 수 있는 배열입니다.
BO[] arr = {a, b, c}에서 일어나는 일을 정확히 말하면: a의 값이 arr[0]에 복사됩니다. 그런데 a는 참조형이므로 a의 값은 객체의 주소입니다. 결국 arr[0]에는 a와 같은 주소가 들어가고, 둘 다 같은 BO 객체를 가리키게 됩니다.
a와arr[0]→ 같은 주소 → 같은 BO 객체(v=1)b와arr[1]→ 같은 주소 → 같은 BO 객체(v=2)c와arr[2]→ 같은 주소 → 같은 BO 객체(v=3)

배열 요소 교환 (참조 교환) 기초
배열의 요소를 교환하면, 배열 안의 주소만 바뀝니다. 원본 변수 a, b, c에 저장된 주소는 변하지 않습니다.
여기서도 같은 원리입니다. BO t = arr[0]은 arr[0]에 저장된 값을 t에 복사합니다. arr[0]의 값은 객체의 주소이므로, t에도 같은 주소가 들어가고 같은 객체를 가리키게 됩니다.
교환 전후 비교
| 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에 저장된 주소는 그대로이므로, a는 여전히 v=1인 객체를 가리킵니다. c도 마찬가지로 여전히 v=3인 객체를 가리킵니다.
배열을 통한 필드 수정 기초
배열 요소를 통해 객체의 필드를 수정하면, 원본 객체가 실제로 변경됩니다. arr[1]과 b에 같은 주소가 들어있으므로, 어느 쪽을 통해 수정하든 같은 객체가 바뀝니다.
교환 후 arr[1]에는 b의 객체 주소가, arr[0]에는 c의 객체 주소가 들어있습니다. 따라서 위 코드는 다음과 같습니다.
b.v가 3으로 변경됩니다. arr[1]과 b는 같은 주소를 가지고 있으므로, arr[1]을 통해 바꾼 것이 b를 통해서도 보입니다. 이것은 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 | 배열 요소가 가리키는 객체의 필드 수정 | 있음 (원본 객체 변경) |