-
[JAVA] Call by Value 와 Call by reference 란 ?Language/Java 2020. 1. 3. 15:29728x90반응형
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/
잘 정리를 해놓으셔서 위 블로그는 참고자료 입니다. ( 이해도 잘되고 보기 좋아서 이 부분도 가져 왔습니다! )
공부한 것을 정리하는 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 함수를 보았는데 자바는 포인터가 없으니까 그냥 값을 넘겨도 되나? 했지만 되지 않았기 때문에 자세히 공부를 해보고자 글을 쓰게 되었다.
글을 너무 이해하기 좋게 정리를 해주셔서 위의 글을 보면서 공부한 것을 정리하려 합니다.
123456789101112131415161718public 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 가 되겠지? 라고 생각을 해서 되나 안되나 테스트를 해보았다.
123456789101112131415161718public 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 구현을 어떻게 해야 된다는 말이지?
123456789101112131415161718192021public 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의 차이를 더 깊게 이해하기 위해서는 "메모리 구조"에 대한 많은 이해가 필요하다고 생각한다.
반응형'Language > Java' 카테고리의 다른 글
[Java] Iterable 과 Iterator 이란? (1) 2020.01.18 [JAVA] next(), nextLine() 의 차이 (4) 2020.01.16 [JAVA] Array.sort 와 Collections.sort 의 차이 (0) 2020.01.13 [JAVA] ArrayList와 LinkedList의 차이 (6) 2020.01.12 [JAVA] 다중 상속(multiple inheritance) 이란? (0) 2020.01.02