Call by Value/Call by Reference

Call by Value/Call by Reference

java에서 인수로 매개 변수를 전달하는 방식이 크게 두가지다.

기본 데이터형은 모두 Call by Value로 처리되고 클래스의 객체는 Call by Reference로 처리 된다.

Call by Value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
}
}
1
2
swap() 호출 전 : a = 10, b = 20
swap() 호출 후 : a = 10, b = 20

인수로 기본 데이터형을 사용하면 모두 Call by Value가 된다.

값을 복사하여 처리하기 때문에 메소드 밖의 변수에는 영향을 미치지 않게 되어 값이 변경되지 않는다.

Call by Reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
}
}
1
2
swap() 호출 전 : a = 10, b = 20
swap() 호출 후 : a = 20, b = 10

CallByReference 클래스의 객체를 생성하여 값을 전달하게 되면 객체가 저장한 값이 주소값이기 때문에 swap메서드에서 변경시킨 결과가 main메서드로 돌려지게 된다.

이렇게 다른 메소드에서 현재의 메소드 내의 변수 값을 바꾸는 현상을 사이드 이펙트(side effect) 라고 한다.

사이드 이펙트 는 메소드 간의 값 전달을 쉽게 하기 때문에 편리하지만, 실수로 프로그래머가 모르는 사이에 값이 바뀌면 심각한 문제를 일으킬 수 있기 때문에 위험하다고 알려져 있다. 그래서 Java는 모든 기본 데이터형은 Call by Value로 값을 주고받아 ‘사이드 이펙트’가 일어나지 않도록 했고, Call by Reference가 필요한 경우는 명시적으로 클래스 객체를 주고받도록 정해둔 것이다.