ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] Call by Value 와 Call by reference 란 ?
    Language/Java 2020. 1. 3. 15:29
    728x90
    반응형

    C언어를 주로 공부 했던 나는 Call by value Call by reference 에 대해서 call by value 는 값을 넘기는 거고 call by reference 는 포인터를 이용해서 주소를 넘긴다고 알고 있다. 하지만 누군가 나에게 이 개념에 대해서 자세히 묻는다면 나도 깊이있게 이해한 것이 아니기 때문에 위에서 말한 대답정도로만 대답을 할 거 같다. 그래서 먼저 이 개념을 한번 더 정리를 한 후에 JAVA 에서의 Call by value 와 Call by reference 에 대해서 알아보겠다. 

     

     

    https://wayhome25.github.io/cs/2017/04/11/cs-13/

     

    강의노트 12. 함수 호출방식(call-by-value, call-by-reference, call-by-assignment) · 초보몽키의 개발공부로그

    패스트캠퍼스 컴퓨터공학 입문 수업을 듣고 중요한 내용을 정리했습니다. 개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.

    wayhome25.github.io

    잘 정리를 해놓으셔서 위 블로그는 참고자료 입니다. ( 이해도 잘되고 보기 좋아서 이 부분도 가져 왔습니다! )

    공부한 것을 정리하는 TIL 공간입니다! 

     

     

    1. call by value (값에 의한 호출)

    • 함수가 호출될 때 메모리 공간 안에서는 임시의 공간이 생성된다. 그리고 함수가 종료되면 해당공간은 사라진다. 
    • 함수 호출시 전달되는 변수의 값을 복사하여 함수의 인자로 전달한다.
    • 복사된 인자는 함수 안에서 지역적으로 사용하는 변수이다.
    • JAVA의 경우 함수에 전달되는 인자의 데이터 타입에 따라서 (기본자료형 / 참조자료형 ) 함수 호출 방식이 달라짐
      • 기본 자료형 : call by value 로 동작 (int, short, long, float, double, char, boolean)
      • 참조 자료형 : call by reference 로 동작 (Array, Class Instance) 

     

    2. call by reference (참조에 의한 호출)

    • 함수가 호출될 때, 메모리 공간 안에서는 함수를 위한 별도의 임시 공간이 생성된다. (함수 종료시 사라짐)
    • call by reference 참조에 의한 호출방식은 함수 호출시 인자로 전달되는 변수의 레퍼런스를 전달한다. (해당 변수를 가르킨다.) 
    • 함수 안에서 인자의 값이 변경되면, 함수 호출시에 있던 변수들도 값이 바뀐다. 

     

     

    이제 Call by value 와 Call by reference 의 차이점을 어느정도 이해했으니 JAVA에서의 두개의 특징을 이해해보자.

    내가 이 글을 쓰게 된 이유는 JAVA 공부를 하던 중에 swap 함수를 보았는데 자바는 포인터가 없으니까 그냥 값을 넘겨도 되나? 했지만 되지 않았기 때문에 자세히 공부를 해보고자 글을 쓰게 되었다. 

     

     

     

    http://dhplanner.blogspot.com/2009/11/java-%EC%97%90%EC%84%9C%EC%9D%98-call-by-value-%EC%99%80-call-by.html

     

    java 에서의 call by value 와 call by reference

    자바에서는 진정한 call by reference는 없고 reference 값을 넘기는 것만 있다고 들었는데, 그 말을 이해하지 못하다가 이제서야 이해하게 되었다.   그 이해를 도와준 포스트가 아래 포스트이다.   ---------...

    dhplanner.blogspot.com

    글을 너무 이해하기 좋게 정리를 해주셔서 위의 글을 보면서 공부한 것을 정리하려 합니다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class SwapTest {
        public static void swap(int a, int b) {
            int tmp = a;
            a = b;
            b = tmp;
        }
     
        public static void main(String[] args) {
            int a = 1;
            int b = 2;
     
            System.out.println(a + " " + b);
            swap(a, b);
            System.out.println(a + " " + b);
            
        }
    }
     
     
     

    다음과 같이 swap 메소드를 만들어서 기본 자료형 a, b 를 인자로 값을 넘겨서 바꿔보려 했다. 하지만 C언어에서는 포인터를 이용하지만 자바에서도.. 그냥 넘기면 안될꺼 같은데?  라는 생각을 했는데 역시나 값은 바뀌지 않는다.

     

    이유는 a, b 는 Call by value 이기 때문이다. (a, b는 기본 자료형의 변수 이기 때문이다)

     

    그래서 위의 블로그의 방식처럼 a,b 를 참조형인 Integer를 이용해서 객체를 생성한 하면 a,b 는 참조 변수가 되므로 Call by reference 가 되겠지? 라고 생각을 해서 되나 안되나 테스트를 해보았다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    public class SwapTest {
        public static void swap(Integer a, Integer b) {
            Integer tmp = a;
            a = b;
            b = tmp;
        }
     
        public static void main(String[] args) {
            Integer a = new Integer(1);
            Integer b = new Integer(2);
     
            System.out.println(a.intValue() + " " + b.intValue());
            swap(a, b);
            System.out.println(a.intValue() + " " + b.intValue());
        }
    }
     
     
     

     

    하지만 역시나 바뀌지 않는다.

     

    그 이유는 뭘까? 나도 생각하지 못했지만 검색으로 알게된 사실은 Call by reference는 맞지만 메소드 호출을 할 때 새로운 reference를 만들어 호출하게 만든다는 점이다.  (new 연산자를 이용할 때와 boxing을 이용해서 값을 할당할 때의 차이점에 대해서 좀 더 찾아보면 이해가 갈 것이다)

     

    따라서 swap 메소드에서도 해당 객체를 가르키지만 다른 reference 값으로 가르킨다는 것이다. 

     

     

     

     

    그러면 JAVA 에서는 Swap 구현을 어떻게 해야 된다는 말이지?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class SwapTest {
        int value;
        
        public SwapTest(int value) {
            this.value = value;
        }
        public static void swap(SwapTest a, SwapTest b) {
            int temp = a.value;
            a.value = b.value;
            b.value = temp;
        }
     
        public static void main(String[] args) {
            SwapTest a = new SwapTest(1);
            SwapTest b = new SwapTest(2);
            System.out.println(a.value + " " + b.value);
            swap(a, b);
            System.out.println(a.value + " " + b.value);
        }
    }
     
     
     

     

    이 코드에 대해서 설명하자면 아까 위에서 말했던 것처럼 객체를 만들어서 참조 변수인 a, b를 넘기면 Call by reference 는 맞다. 하지만 같은 객체를 가르키는 새로운 reference 값이 생긴다고 했다. 그래서 그 새로운 참조변수 값으로 swap 함수에서 값을 바꿔놓는 것이다.

     

    따라서 가장 중요하게 알아놔야 될 것은

     

    JAVA에서 Call by reference는 해당 객체의 주소값을 직접 넘기는 게 아닌 객체를 보는 또 다른 주소값을 만들어서 넘기다는 사실을 꼭 기억하자. 

     

     

    Call by reference와 Call by Value의 차이를 더 깊게 이해하기 위해서는 "메모리 구조"에 대한 많은 이해가 필요하다고 생각한다.

    반응형

    댓글

Designed by Tistory.