자바에는 두 가지 타입이 있습니다. 기본 타입은 byte, char, short, int, long, float, double, boolean이 있어요. 참조 타입은 객체를 가리키는 변수인데요. 이들이 어떻게 다른지 예제 프로그램과 그림으로 설명해 보도록 하겠습니다.

 

 


 

 문제의 예제 프로그램입니다. 7번째 줄까지 수행이 되면, 메모리에 다음과 같이 올라갑니다.

 

 

 n과 m은 기본형으로 선언된, 변수들입니다. 즉, 실제 값을 저장하고 있습니다. 8번째 줄에 2차원 배열인 arr을 선언했는데요. 이는 기본형이 아닙니다. 즉 참조형이라는 이야기인데요. 이것은 실값을 저장하지 않습니다. 참조값을 저장해 놓습니다.

 

 

 그러면 arr은 실값을 저장해 놓았나요? 아닙니다. 객체를 참조하는 어떠한 값을 저장해 놓습니다. 이것이 기본 타입과의 차이점이라고 할 수 있어요. 바깥쪽 for문에 String st = ""; 으로 초기화가 되어 있습니다.

 

 

 이 ""은 리터럴 풀에 저장이 되어 있겠네요. 그것을 st가 가리키고 있습니다.

 

 

 st = st + arr[i][j] + " "이 수행되는 순간에 어떻게 될까요? 일단 arr[0][0]에는 0이, arr[0][1]에는 1이 저장이 될 겁니다. 이것만 과정으로 보여봅시다. 먼저, StringBuilder 객체를 내부에서 생성합니다. 그리고 그것을 _new가 가리킬 겁니다. 참조형입니다.

 

 StringBuilder에는 내부에 append 메서드가 있는데요. '1'과 ' '을 추가하라고 했습니다.

 

 

 그러니 StringBuilder 객체에는 '1'과 ' '가 append 되었을 거고, 이것을 toString() 메서드로 변환을 하면, String 형이 리턴이 됩니다. 그러면 내부에서 String 객체가 새로 생성이 될 겁니다.

 

 

 그리고 그 객체를 st가 가리키니까, st는 다음과 같겠네요. 보라색으로 칠한 것은 리터럴 풀이기 때문에 아직 어딘가에서 참조하고 있지만, 노란 부분은 참조하고 있지 않습니다. 이제 '2'와 ' '를 추가해 봅시다.

 

 

 그러면 StringBuilder 객체를 하나 추가할 겁니다. 그리고 그것을 참조 변수가 가리킬 겁니다. 새로 추가한 객체에 '2'와 공백 문자인 ' '를 append 합니다.

 

 

 그 다음에 이것을 toString()으로 변환하고, 이를 st에 대입합니다.

 

 

 그러면 StringBuilder 객체와 String 객체인 "1 "은, 가비지가 될 겁니다. st는 객체 "1 2 "를 가리키기 때문입니다.

 

 


 참조 변수를 대입할 때에는 조심해야 합니다. 즉, 이는 참조변수 값을 필드를 가지는, 객체를 내용 복사할 때 조심해야 한다는 이야기입니다. 아래 프로그램을 봅시다.

 

 

 저는 배열 객체 arr을 선언하고, 0번째 원소에 0을, 1번째 원소에 1을 넣었습니다.

 

 

 8번째 줄까지 수행하고 난 후의 상황입니다. 참조 변수 arr이 배열 객체 [0 1]을 가리키고 있습니다. 9번째 줄을 잘 보시면, int []brr = arr; 이라고 되어 있는데요. 이는 arr의 참조 변수의 값을 brr에 넣겠다는 이야기입니다. 즉, brr도 객체 [0 1]을 참조한다는 소리가 됩니다.

 

 

 정확히 이런 상황입니다. 이를 '얕은 복사'라고 합니다. 어찌 되었던, 참조하는 곳을 공유하기 때문에, brr[0]에 2를 대입하면, 원본인 arr도 변경이 일어나 버립니다.

 

 

 arr[0]을 출력했을 때, 0이 아닌 2가 나온다는 것. 그려지실 거에요. 이는 나중에 Clone 메서드나 ArrayCopy 등을 설명할 때에도 다시 이야기 해 보도록 하겠습니다. 그러니, 여기에서는 그냥 아 이러한 것 때문에 머리가 아프겠구나. 정도만 이해하셔도 좋겠습니다. 정리해 봅시다. 기본 타입은 실값을 저장해요. 참조 타입은 실 값을 저장하지 않습니다. 어디를 참조하는지를 저장합니다. 이 둘의 차이점을 짚고 넘어가시면 좋을 듯 싶습니다.