본문 바로가기
JAVA

[JAVA] call by value 와 call by reference

by Amy IT 2022. 5. 24.

메소드를 호출해서 특정 인자를 전달할 때 자바는 call by value 방식으로 전달됩니다. 즉, 값 복사를 통해서 인자가 전달됩니다. 그런데 이때 기본형 데이터인 경우와 참조형 데이터인 경우 각각 인자로 전달되는 값이 달라집니다.

 

 

◆ 기본형 데이터 - call by value 값에 의한 호출

 

기본형 데이터는 call by value 방식으로 값이 전달됩니다. 즉, 메소드를 호출해서 특정 값을 전달할 때 변수에 저장된 실제 데이터 값을 복사하여 전달합니다. 다음의 예시를 살펴보겠습니다.

public class Test {

	private static void change(int x) {//xxx변수 값을 x(매개변수)가 받음
		System.out.println("in change 함수 x= "+ x);
		x=20; //x값 변경
	}//end change 
	
	public static void main(String[] args) {
		int xxx = 10; 
		System.out.println("호출전 xxx= "+xxx);
		change(xxx);		
		System.out.println("호출후 xxx= "+xxx); 
	}//end main

}//end class

메인 함수에서 xxx 변수에 10을 저장한 후 값을 출력하고, change 함수를 호출하여 xxx 값을 전달하고 있습니다. change 함수는 매개변수 x를 통해 10 값을 전달 받고 값을 출력한 후, x값을 20으로 변경하고 있습니다. 그렇다면 다시 메인 함수로 돌아가 호출 후 xxx 값을 출력하면 10이 나올까요, 20이 나올까요? 정답은 10입니다.

 

x는 매개변수로서 전달받은 값을 복사하여 저장하였을 뿐, xxx와 x는 서로 다른 변수이기 때문입니다. x는 change 함수에서 선언된 로컬변수로서 change 함수가 끝나면 사라집니다. 이렇게 기본형 데이터는 메소드를 호출하여 인자를 전달할 때 실제 데이터 값이 복사되기 때문에, 전달받은 곳에서 값을 변경해도 원래 값은 변경되지 않습니다.

 

 

 

◆ 참조형 데이터 - call by reference 참조에 의한 호출

 

이에 반해 참조형 데이터는 call by reference 방식으로 값이 전달됩니다. 즉, 메소드를 호출해서 특정 값을 전달할 때 실제 데이터 값을 복사해서 넘겨주지 않고, 참조하고 있는 객체의 주소값을 전달합니다. 다음의 예시를 살펴보겠습니다.

public class ArrayTest3 {

	private static void change2(int[] x) { 
		x[2]=100;
	}
    	private static void change3(int i) { 
		i=1;
	}

	public static void main(String[] args) { 
		int [] num = new int[3];
		num[0]=10;
		num[1]=20;
		num[2]=30;
		System.out.println("호출전 : "+num[2]);
		change2(num); 
		System.out.println("호출후 : "+num[2]);

		change3(num[0]);
		System.out.println("호출후 : "+num[0]);
	}//end main

}//end class

3개의 방을 가진 int 타입의 배열을 생성해 num이란 변수에 참조시킨 후, 각 방에 값을 저장하고 있습니다. 호출 전 num[2] 값은 현재 30입니다. 이후 change2 함수를 호출하며 num을 넘겨주고 있습니다. num은 int 타입 배열로서 참조형 데이터입니다. change2 함수의 매개변수는 전달받는 값과 동일한 데이터 형이어야 하므로 마찬가지로 int 타입의 배열로 설정해 주고 있습니다. num 배열을 받은 후, 2번 방의 값을 100으로 변경하고 있습니다. change2 함수가 끝난 후 다시 메인으로 돌아가 호출 후 num[2] 값을 출력하면 30이 나올까요, 100이 나올까요? 정답은 100입니다. 

 

int [] x 역시 change2 함수에서 선언된 로컬변수로서, change2 함수가 종료되면 변수가 사라집니다. 하지만 change2 함수가 호출되며 전달받은 값은 num이라는 참조변수가 참조하고 있는 배열의 주소값입니다. 즉, num이라는 참조변수와 x라는 참조변수가 똑같은 주소값을 갖게 되며, 따라서 동일한 배열을 참조하게 됩니다. 이 때문에 전달받은 곳에서 참조하고 있는 객체의 값을 변경하면 원래 값도 변경되는 것입니다. 

 

change3 함수를 호출하면서 num[0] 이라는 기본형 데이터를 다시 전달해 보겠습니다. 현재 num[0]에 저장된 값은 10입니다. change3 함수가 매개변수 i를 통해 num[0] 값을 받은 후, i를 1로 변경하고 있습니다. 다시 메인에서 호출 후 num[0] 값을 출력하면 어떤 값이 나올지 예상할 수 있습니다. 

 

num[0]은 0번 방에 저장된 int 타입 기본형 데이터입니다. 따라서 10이라는 실제 데이터의 값이 i라는 로컬변수에 복사되어 저장된 후 i가 1로 바뀌었을 뿐, 실제 0번 방의 데이터는 그대로인 것을 확인할 수 있습니다. 

 

 

데이터 형이 기본형인지 참조형인지에 따라, 메소드 호출 시 인자 값을 전달하는 방식이 call by value, call by reference로 달라지는 것을 알아볼 수 있었습니다. 그런데 참조형 데이터 역시 주소값을 복사하여 전달하는 것이기 때문에 기본적으로 값을 복사하여 인자를 전달하는 call by value 방식이라고 할 수 있습니다. 이 때문에 자바는 call by value 방식으로만 값을 전달한다고 말하는 것입니다. 이에 대한 깊은 이해는 메모리에 대한 이해가 선행되어야 하기 때문에, 여기서는 이 정도로 글을 마무리하도록 하겠습니다. 이상으로 기본형 데이터와 참조형 데이터가 메소드 호출 시 어떤 값으로 전달되는지에 대해 알아보았습니다. 

 

 

댓글