ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] Call by value와 Call by reference
    프로그래밍/Java 2017. 5. 31. 17:20

    이번에 다룰 주제는 Call by value, Call by reference 입니다.


    함수의 호출 방식에는 Call by value와 Call by reference가 있습니다.

    말 그대로 '값에 의한 호출'이냐, '참조에 의한 호출'이냐 라고 할 수 있는데요, 그럼 어떤 차이가 있는지 예제를 통해 알아보겠습니다.



    Call by value

    Call by value와 Call by reference의 설명으로 자주 등장하는 swap 예제입니다.

    일단 먼저 예제를 보겠습니다.


    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() 메서드에 a, b를 넘겼으니까 값이 바껴야 하는거 아냐?"


    네, 아닙니다. 결론을 먼저 말씀드리자면 swap() 메서드 호출 시에 사용한 인자 a, b swap() 메서드내의 매개변수 x, y 서로 다르기 때문입니다.

    아래 그림을 보시면 이해가 빠르게 되실겁니다.




    main()에서 선언 된 변수 a와 b가 각각 메모리의 0x0001번지와 0x0005번지에 할당 되었다고 가정합니다. 할당 된 메모리 변수에는 각각 10과 20의 값이 저장됩니다. 이후, swap() 메서드 호출 시에 사용한 인자 a와 b는 할당 된 메모리 주소가 아닌 메모리에 담겨져 있던 값만이 복사되어 swap() 메서드 내부의 매개변수 x와 y의 메모리 주소에 담겨지게 됩니다. 당연하게도 swap() 메서드가 수행하는 동안 사용되는 변수들은 main()에 존재하는 a와 b가 아닌 swap() 내부에 새로 생성 된 x와 y이기 때문에 메서드 수행 후에도 결과 값에 변화가 없습니다.


    장황하게 설명한 것 같지만, 요점은 다음과 같습니다.


    Call by value는 메서드 호출 시에 사용되는 인자의 메모리에 저장되어 있는 값(value)을 복사하여 보낸다.


    그럼 이어서, Call by reference에 대해 알아보겠습니다.


    Call by reference

    Call by reference는 메서드 호출 시에 사용되는 인자가, 값이 아닌 주소(Address)를 넘겨줌으로써, 주소를 참조(Reference)하여 데이터를 변경할 수 있습니다.

    이번에도 위와 비슷한 예제를 보도록 하겠습니다.


    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번지를 가리키고 있기 때문에 변한 데이터를 불러들여 결과 값이 변하게 됩니다.


    Call by reference는 메서드 호출 시 사용되는 인자 값의 메모리에 저장되어있는 주소(Address)를 복사하여 보낸다.





    이해가 좀 되셨나요?

    사실 자바는 Call by value이냐, Call by reference이냐 로 의견이 분분합니다.

    메모리에 저장 된 주소를 보내는 것도 물리적 관점에서 보면 값으로 볼 수 있기 때문인데요, 이 문제에 대해서도 한번 생각해 보신다면 좋을 것 같습니다.


    이상으로 포스팅을 마치겠습니다.

    '프로그래밍 > Java' 카테고리의 다른 글

    [Java] 메모리 구조  (1) 2017.05.30
Designed by Tistory.