Java | Call by value, Call by reference

송은석·2022년 11월 12일
1
post-custom-banner

Call by value, Call by reference.

이 둘은 함수나 메소드에 매개 변수를 전달하는 방식을 뜻한다.

간단히 말해서 Call by value는 매개 변수로 변수에 할당되어 있는 값을 복사하여 전달하는 것을 말하고,

Call by reference는 매개 변수로 변수 자체의 주소 값을 복사하여 전달하는 것을 말한다.

Call by reference는 Java나 C에서는 사용할 수 없으며, C++에서 사용 가능하다.

// c++

int main() {
	int a,b;
  callByRef(a,b)
}

int callByRef(int &c, int &d) {
   c = 1;  // 매개 변수 c와 d를 위의 a, b와 동일하게 사용할 수 있다. 
   b = 2;  // main()의 a,b의 값이 변경된다.
}

위 코드는 main()의 a, b 변수의 주소 값을 callByRef()에 전달해주었기 때문에 가능하다.
이처럼 전달된 매개 변수를 마치 alias 처럼 사용할 수 있을 때, 이를 call by reference라고 한다.

C에서도 포인터를 사용하여 Call by reference와 비슷하게 보이도록 사용할 수는 있다. (포인터를 통해 Call by reference를 구현했다고 할 수 있다.)


한편, 자바는 매개 변수로 reference를 넘기지 않는다.

Java가 Call by reference처럼 보일 때

물론 Java가 Call by reference처럼 보일 때가 있다. 가령 Array와 같은 객체를 매개 변수로 넘기고 나서 메소드에서 매개 변수의 내용을 수정하면, 전달된 객체가 수정되는 모습을 보게 될 때 그런 생각이 든다. (사실 이게 헷갈려서 이 포스트까지 쓰게 되었다.)

public class Test {
    public static void main(String [] args) {
        int [] arr = {1, 2, 3};
        callByValue(arr);

        System.out.println(arr[0]); // 3, arr가 수정됨.  
    }

    public static void callByValue(int [] arr){
	      arr[0] = 3; 
			  // arr = new int []{ 2, 3, 4};
    }
}

그러나 Java는 명백히 Call by value다.

위의 코드를 보았을 때 매개 변수로 reference를 준 것처럼 보이기도 하지만, 사실 이는 변수에 할당된 값에 대한 메모리 주소 값을 복사하여 넘겨준 것이다.

즉, arr에는 실제 배열의 값이 담겨 있는 메모리의 시작 주소 값이 기록되어 있으며, arr를 callByValue 메소드의 매개 변수로 넘겨줄 때 단지 arr에 기록되어 있는 주소 값을 넘겨준 것이다. 이는 변수 자체의 주소 값을 넘겨주는 Call by reference와는 다른 것이다.

위의 코드에서는 넘겨 받은 주소 값을 참조하여 배열 내의 값을 수정했으므로 값이 수정될 수 있었다. 이 또한 reference를 받아 수정한 것과는 다른 것이다.


arr의 reference를 넘겨주지 않았다는 것은 위 코드의 주석을 해제하는 것 만으로도 증명할 수 있다.

public class Test {
    public static void main(String [] args) {
        int [] arr = {1, 2, 3};
        callByValue(arr);

        System.out.println(arr[0]); // 1, arr가 수정되지 않음.
    }

    public static void callByValue(int [] arr){
	      // arr[0] = 3;
			  arr = new int []{ 2, 3, 4};
    }
}

main 메소드 안의 arr는 수정되지 않았다. 이는 callByValue 메소드로 전달한 것이 단지 arr에 저장된 배열에 대한 주소 값이었기 때문이다.

기본 자료형 변수가 저장하고 있는 값을 그 값 자체로 판단한다면, 참조 변수는 저장하고 있는 값을 주소로 판단한다고 이해하면 쉽다.


정리하면, Call by value는 변수에 담겨 있는 값(그것이 원시 값이든, 메모리의 주소 값이든 간에)을 전달하고, Call by reference는 변수 자체의 주소 값을 전달한다.

참고

책 | 스프링 입문을 위한 자바 객체 지향의 원리와 이해, 김종민, 2022
웹 사이트 | https://umbum.dev/114
웹 사이트 | https://gyoogle.dev/blog/computer-language/Java/Call%20by%20value%20&%20Call%20by%20reference.html
profile
Done is better than perfect🔥
post-custom-banner

0개의 댓글