Call by Value는 함수의 인자를 전달할 때 '값을 전달하는 방식'이고
Call by Reference는 '주소를 전달하는 방식'입니다. 자바는 Call by Value 방식을 사용합니다. 이제 자바가 어떤 방식으로 Value 전달을 하는지 알아보겠습니다.
swap 예제로 Call by Value를 알아보겠습니다.
public Class CallbyValue {
public static void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("swap() 호출 전 : a = " + a + ", b = " + b);
swap(a, b);
System.out.println("swap() 호출 후 : a = " + a + ", b = " + b);
}
}
결과
swap() 호출 전 : a = 10, b = 20
swap() 호출 후 : a = 10, b = 20
결과를 보면 swap()을 하였지만 동일한 결과가 나오는 것을 알 수 있습니다. 아래의 메모리 구조 그림을 참고하면 이유를 정확히 알 수 있습니다.
main()에서 선언 된 변수 a와 b가 각각 메모리의 0x0001번지와 0x0005번지에 할당 되었다고 가정합니다. 할당 된 메모리 변수에는 각각 10과 20의 값이 저장됩니다.
이후, swap() 메서드 호출 시에 사용한 인자 a와 b는 할당 된 메모리 주소가 아닌 메모리에 담겨져 있던 값만이 복사되어 swap() 메서드 내부의 매개변수 x와 y의 메모리 주소에 담겨지게 됩니다.
swap() 메서드가 수행하는 동안 사용되는 변수들은 main()에 존재하는 a와 b가 아닌 swap() 내부에 새로 생성 된 x와 y이기 때문에 메서드 수행 후에도 결과 값에 변화가 없습니다.
Call by reference는 메서드 호출 시에 사용되는 인자가, 값이 아닌 주소(Address)를 넘겨줌으로써, 주소를 참조(Reference)하여 데이터를 변경할 수 있습니다. 그런데 자바는 객체를 참조하게 해서 그 안의 값을 바꿔주게 됩니다. 결국에는 주소값을 바꾸는 것이 아니라 안의 값을 바꿔주기 때문에 Call by value 가 되는것을 알 수 있습니다. 자세한 것은 아래에서 더 알아보겠습니다.
public Class Callbyreference {
int value;
Callbyreference(int value) {
this.value = value;
}
public static void swap(Callbyreference x, Callbyreference y) {
int temp = x.value;
x.value = y.value;
y.value = temp;
}
public static void main(String[] args) {
Callbyreference a = new Callbyreference(10);
Callbyreference b = new Callbyreference(20);
System.out.println("swap() 호출 전 : a = " + a.value + ", b = " + b.value);
swap(a, b);
System.out.println("swap() 호출 전 : a = " + a.value + ", b = " + b.value);
}
}
결과
swap() 호출 전 : a = 10, b = 20
swap() 호출 후 : a = 20, b = 10
이번에는 a와 b의 값이 바뀌어서 나온 것을 확인 할 수 있습니다.
main()에서 선언 된 Callbyreference 타입의 변수 a와 b는 각각 객체를 생성하여 0x0001번지와 0x0005번지에 저장된 10과 20의 주소 값을 저장하게 됩니다.
이후, swap() 메서드 호출 시에 인자 a와 b는 메모리에 저장 된 주소 값을 복사하여 매개변수 x와 y의 메모리에 저장합니다. 결국 swap() 메서드는 10과 20이 저장 된 0x0001번지와 0x0005번지의 주소를 참조하여 연산하기 때문에, 연산 결과에 따라 원본 데이터가 변하게 됩니다.
main()에서 선언 된 변수 a와 b는 각각 0x0001번지와 0x0005번지를 가리키고 있기 때문에 변한 데이터를 불러들여 결과 값이 변하게 됩니다.
즉, 자바는 객체를 메서드로 넘길 때 객체를 참조하는 지역변수의 실제 주소를 넘기는 것이 아니라 그 지역변수가 가리키고 있는 힙 영역의 객체를 가리키는 새로운 지역변수를 생성하여 그것을 통하여 같은 객체를 가리키도록 하는 방식입니다.