본문 바로가기
언어/Java

[Java] Call by value & Call by reference

by Geunny 2020. 7. 29.
반응형

프로그래밍에서 함수의 호출 방식으로 

Call by value 와 Call by reference 방식이 있다.

 

이는 함수에 매개변수를 넘겨줄 때

'값(value)'을 넘겨주느냐

'주소(reference)'를 넘겨주느냐는 차이에서 생겨난 용어이다.

 

Call by value

먼저 c 언어로 되어있는 예시를 보자.

#include <stdio.h>

void swap(int a, int b){
	int temp;
	
	temp = a;
	a = b;
	b = temp;
}

int main(){
	int a, b;
	
	a = 10;
	b = 20;
	
	printf("swap 전 : %d %d\n", a, b);
	
	swap(a, b);
	
	printf("swap 후 : %d %d\n", a, b);
	
	return 0;
}

스스로 이해해본 결과 이는

main 에 있는 a,b 변수와 함수에 있는 a,b 변수는 결국 값은 갖지만 다른 변수이며

main 에있는 a,b 변수가 swap 함수에 인자로 들어갔을 때

  함수 안에 있는 a,b 지역변수에 main 함수의 a,b의 값이 대입되었다고 볼 수 있다.

 

이는 자바에서도 마찬 가지로 적용된다.

 

public class CallByValue {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		System.out.printf("a: %d, b: %d\n",a,b);
		swap(a,b);
		System.out.printf("a: %d, b: %d\n",a,b);
	}

	public static void swap(int a, int b) {
		int temp = a;
		a = b;
		b = temp;
	}
}

 Call by reference

함수에서 값을 전달하는 대신 주소값을 전달하는 방식을 call by reference라고 한다.

그러나 Java 에서는 함수의 개념이 없다. 함수와 유사한 객체의 method 개념이 있다.

또한 Java 에서는 객체간 전달을 할 때 Call by reference 가 이루어 지지 않는다.

 

다음 예시를 통해 확인해보자.

public class JavaCallByValue {
    public static void main(String[] args) {
        MyClass myClass1 = new MyClass(1);
        MyClass myClass2 = new MyClass(2);

        // 변경전
        System.out.println("변경전 myClass1: "+myClass1.getIndex()); //출력결과 1
        System.out.println("변경전 myClass2: "+myClass2.getIndex()); //출력결과 2

        //두개의 참조를 바꿔 보자
        swapReference(myClass1, myClass2);
        System.out.println("변경후 myClass1: "+myClass1.getIndex()); //출력결과 1
        System.out.println("변경후 myClass2: "+myClass2.getIndex()); //출력결과 2
    }

    static void swapReference(MyClass m1, MyClass m2) {
        MyClass tmp = m1;
        m1 = m2;
        m2 = tmp;
    }

}

class MyClass{
    int index;

    public MyClass(int index) {
        this.index = index;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
}

 

해당 코드는 MyClass 라는 객체를 만들어 해당 객체를 swapReference 매서드로 두 객체를 교환하였다.

만약 call by reference 가 이루어 졌다면 두번째 변경후 출력문에서 두 객체가 변경될것 같지만

출력을 해보면 다음과 같이 나타난다.

변경이 안됨.

처음 이러한 결과를 보게된후 정말 이해가 되지 않았다.

왜 객체를 넣었는데 바뀌지 않지?

 

위의 코드를 매서드로 실행하지 않고 main문에서 진행하면 다음과 같이 이뤄진다.

        MyClass myClass1 = new MyClass(1);
        MyClass myClass2 = new MyClass(2);

        // 변경전
        System.out.println("변경전 myClass1: "+myClass1.getIndex()); //출력결과 1
        System.out.println("변경전 myClass2: "+myClass2.getIndex()); //출력결과 2

        //매서드 사용 없이 바로 바꿈

        MyClass temp = myClass1;
        myClass1 = myClass2;
        myClass2 = temp;

		System.out.println("변경후 myClass1: "+myClass1.getIndex()); //출력결과 1
        System.out.println("변경후 myClass2: "+myClass2.getIndex()); //출력결과 2
        

이번엔 바뀜;;;

 

위와 같이 main 문에서 직접 변경 하였을 때는 두 객체가 바뀌엇으나

매서드의 인자로 이용한다면 바뀌지 않은 이유를 내 방식대로 해석해 보았다.

 

첫번째 같은 경우, method의 매개변수로 객체를 받을때

매서드의 지역변수 m1, m2 에 main문의 두 객체의 주소를 받게된다.

 

 

이 두 객체는 결국 main문의 두 클래스의 주소를 가르키고 있지만

근본적으로 main 문의 두 객체와는 다른 객체인 샘이다.

 

그 이후 메서드 안에서 m1, m2 를 서로 바꾸게 되지만

바뀐 값은 결국 매서드 안의 지역변수가 변경되는 것이지

main문 안의 두 객체가 변경되는 것이 아니다.

 

 

또한 method가 끝나게 되면 m1, m2는 반환을 하지 않아

사라지게 된다.

 

그렇다면 두 객체를 바꿀수 없는 것인가?

 

그렇지는 않다. 해당 객체들을 변경하는 것이 아니라

해당 객체들의 매서드를 이용하게 되면 변경이 가능하다.

또는 매서드의 각 파라미터들을 반환시킨다면 변경이 가능 할 것이다.

 

 

 

그러므로..  객체를 직접 주입해서 사용할 때는 마치 Call by value로 작용 하는것 같지만

해당 객체의 매서드를 직접 이용한다는 점에서 Call by reference로 작용하는것 과 같다고 볼수 있다.

 

 

자바의 참조형이 Call by Value냐 Call by Reference냐 라는 물음에 대한 답은 Call by Value가 맞는 것 같습니다. 그런데 제가 공부하면서 느낀 건 자바의 참조형이 Call by Reference인지 아닌지 엄밀히 구분할려는 것 자체가 무의미 하다는 것입니다. 이런 혼동의 원인은 아마도 C언어에 익숙한 프로그래머 들의 잔재(?)가 아닐까 합니다. 애초에 C언어에서는 Call by Value와 Call by Reference를 문법적으로 구분이 가능하지만, 자바는 문법적으로 구분이 불가능 합니다. 자바의 메소드(함수) 호출 방식은 그냥 자바의 호출 방식으로만 이해하면 됩니다.

(출처 - https://siyoon210.tistory.com/104 블로그 주인장님의 주장..)

 

 

참고 사이트 - https://siyoon210.tistory.com/104

 

자바의 메소드(함수) 호출 방식 - Call by Value vs Call by Reference

메소드(함수) 호출 방식 프로그래밍 언어에서 변수를 다른 함수의 인자로 넘겨 줄 수 있습니다. 이 때 이 변수의 '값'을 넘겨 주는 호출 방식을 Call by Value, 이 변수의 '참조값' (혹은 주소, 포인터

siyoon210.tistory.com

https://edu.goorm.io/learn/lecture/201/%EB%B0%94%EB%A1%9C-%EC%8B%A4%ED%96%89%ED%95%B4%EB%B3%B4%EB%A9%B4%EC%84%9C-%EB%B0%B0%EC%9A%B0%EB%8A%94-c%EC%96%B8%EC%96%B4/lesson/412515/call-by-value-and-call-by-reference

 

구름EDU - 모두를 위한 맞춤형 IT교육

구름EDU는 모두를 위한 맞춤형 IT교육 플랫폼입니다. 개인/학교/기업 및 기관 별 최적화된 IT교육 솔루션을 경험해보세요. 기초부터 실무 프로그래밍 교육, 전국 초중고/대학교 온라인 강의, 기업/

edu.goorm.io

 

댓글