함수의 인자 전달 방식
컴퓨터 관련 학과를 전공한 사람이라면 대부분 Call by Value, Call by Reference, Call by Name과 같은 용어를 들어봤을 것이다.
해당 용어들은 함수에게 인자를 전달하는 방식을 의미한다.
각각이 무엇인지 차근차근 알아보도록 haza~
Call by Value (값에 의한 호출)
함수가 인자로 전달받은 값을 복사하여 처리하는 방식이다.
변수의 복사본이 전달되기 때문에, 함수 내에서 값을 변경해도 원본 값은 바뀌지 않는다.
Call by Reference (참조에 의한 호출)
함수가 인자로 전달받은 값의 주소를 참조하여 처리하는 방식이다.
변수 자체가 전달되기 때문에, 함수 내에서 값을 변경하면 원본 값도 바뀐다.
Call by Name (이름에 의한 호출)
해당 용어는 두 가지로 해석된다.
- 매개변수 없이 이름으로만 호출하는 메서드
- 함수로 전달된 인자의 값이 실제로 사용될 때 평가되는 방식
두번째 의미는 스칼라와 같은 언어에서 값이 필요할 때마다 평가하는 방식이다.
스칼라는 함수 자체를 값으로 사용할 수 있기 때문에, 함수의 인자로 또 다른 함수를 전달할 수 있다.
이때, 인자로 전달된 함수를 실제로 사용할 때 해당 함수가 의미하는 게 무엇인지 평가하는 것이다.
Java에서의 인자 전달 방식
먼저, 자바에서의 데이터 타입은 크게 2가지로 분류된다는 것을 알아야 한다.
- 원시 타입 (Primitive type) : 실제 데이터 값을 저장하는 자료형
- byte, short, int, float, long, double, char, boolean
- 참조 타입 (Reference type) : 객체의 주소를 저장하는 자료형
- Class, Interface, Array, Enum, String
결론부터 말하자면, 자바는 항상 Call by Value 방식으로 동작한다.
원시 타입
public class Main
{
public static void main(String[] args)
{
int value = 10;
add(value);
System.out.println(value); // 10
}
static void add(int num)
{
num++;
}
}
위 코드를 보자.
add 메서드의 인자로 value를 전달하지만, value의 값은 여전히 10이다.
자바에서는 매개변수와 지역변수를 스택 메모리 영역에서 관리한다.
해당 스택 영역에서 각각의 메서드 영역은 구분되며, 각자 서로 다른 변수를 가지고 있다.
따라서, num 변수에 1을 더해도 value 변수에는 아무런 영향이 없다.
원시 타입의 전달은 딱봐도 Call by Value 방식인 것을 확인할 수 있다!
참조 타입
public class Main
{
public static void main(String[] args)
{
int[] value = { 10 }; // 0x001
add(value);
System.out.println(value[0]); // 11
}
static void add(int[] num)
{
num[0]++;
}
}
위 코드를 보자.
이전의 코드와 다르게 원시 타입(int)가 아닌 참조 타입(int[])을 사용하고 있다.
add 메서드 내에서 배열의 첫 번째 값을 변경하니, 기존 값도 바뀐 것을 확인할 수 있다!
자바에서 참조 타입은 스택 내의 변수가 힙의 실제 값을 가리키도록 설계되어 있다.
따라서, num 변수의 0 번째 값에 1을 더하면 힙의 값이 변경되기 때문에, 동일한 영역을 가리키는 value 변수에도 반영되는 것이다.
그렇다면 참조 타입은 Call by Reference 방식으로 동작하는 것일까?
그렇지 않다!
자바에서는 참조 타입도 Call by Value 방식으로 동작한다.
말이 앞뒤가 안맞잖아!
아닌데? 자바에서의 참조와 Call by Reference에서의 참조는 의미가 약간 다르다.
자바에서는 실제 객체에 대한 참조를 전달하는 것이 아닌, 객체에 접근하고 조작하는 방법을 전달한다.
그러나, Call by Reference는 참조 자체를 넘기는 방식이다.
public class Main
{
public static void main(String[] args)
{
int[] value = { 10 }; // 0x001
add(value);
System.out.println(value); // 0x001
}
static void add(int[] num)
{
num = new int[1]; // 0x002
num[0] = 11;
}
}
위는 이전 코드와 다르게, num 변수에 새로운 배열을 할당하고 있다.
자바가 Call by Reference 방식으로 동작한다면, 위 출력문의 결과는 "0x002"여야 한다.
그러나, 실제 출력은 "0x001"이다.
왜냐하면, num 변수가 가리키는 힙 영역이 바뀔 뿐, value 변수에는 영향이 없기 때문이다!
이처럼, 자바는 항상 Call by Value 방식으로 데이터를 전달한다.
즉, 인자로 전달하는 원본 변수와 메서드의 매개변수는 스택 영역 내에서 각각 독립적으로 존재한다!
참고 :
https://dev-coco.tistory.com/189
'개발' 카테고리의 다른 글
대규모 트래픽에 대처하는 방법 (1) | 2025.06.02 |
---|---|
equals & hashCode (0) | 2025.05.28 |
파티셔닝과 샤딩 (0) | 2025.05.19 |
[ Spring Boot + Prometheus + Grafana ] 모니터링 도입 (0) | 2025.05.18 |
[ NAVER D2 ] 네이버페이 주문에 적용된 확장 가능한 대기열 개발기 (0) | 2025.05.14 |