Call by Value, Call by Reference
- 메서드를 호출할 때 파라미터를 전달하는 방법
Call by Value
- 메서드를 호출할 때 인자의 값을 그대로 복사해서 함수에 전달하는 방식입니다.
- 메서드를 호출하는 호출자 (Caller)의 변수와 호출당하는 수신자 (Callee)의 파라미터는 복사된 서로 다른 변수입니다.
- 값만을 전달하기에 수신자의 파라미터를 수정해도 호출자의 변수는 변경되지 않습니다.
- 메서드를 호출하는 순간에 복사본이 생성되며, 복사본의 값만 변경되며 원본의 값은 변경되지 않습니다.
- Java에서는 call-by-value로 동작합니다. (값을 복사, 주소값을 복사)
Call by Reference (Java X, 100% Call by Value 방식)
- 메서드를 호출할 때 인자의 메모리 주소(참조)를 함수에 전달하는 방식입니다.
- 참조값을 직접 넘기기 때문에 변수와 수신자의 파라미터는 완전히 동일한 변수입니다.
- 메서드 내에서 파라미터를 수정하면 그대로 원본 변수에도 반영됩니다.
- 값 자체를 복사해야 하는 방식의 Call by Value와 비교하면, 주소(포인터)만 복사하면 되기에 일반적으로 복사 비용은 적습니다.
- Java에서는 C/C++ 처럼 포인터를 노출하지 않고, 주소연산자(&)를 이용해 직접적인 메모리 참조가 불가능하기에 call by reference라는 개념이 존재하지 않습니다.
Java에서의 Parameter 전달 메커니즘
- 해당 글 (JVM Memory 구조 포스팅)에서 reference type, primitive type은 모두 stack area에 존재하는 것을 확인할 수 있습니다. (객체 정보는 제외)
- Primitive Type
- 메서드를 인자와 함께 호출하는 순간 primitive type의 경우에는 각 변수에 대한 복사본을 생성하여, stack memory 다른 위치에 저장되게 됩니다. 그래서 원본 변수는 값을 그대로 유지하게 됩니다.
- Reference Type
- reference type의 경우는 객체 정보는 heap area, 객체를 참조 값은 stack area에 동적으로 저장됩니다. 이러한 객체들은 참조 변수(reference variable)를 통해 접근합니다.
- Java의 객체는 Primitive Type과 달리 두 단계로 저장됩니다.
- 참조 변수는 stack area, 객체는 heap 메모리에 저장됩니다.
- 객체를 메서드 인자로 전달하면, 참조 변수의 복사본이 생성되어 원래 참조 변수가 가리키는 동일한 힙 메모리 주소를 가리키게 됩니다.
- 메서드 내부에서 같은 객체의 속성을 변경하게 되면, 그 변경 사항이 원본 객체에도 반영됩니다. (주소값을 넘겨받아서 같은 객체를 바라보기 때문입니다.)
- 하지만, 메서드 안에서 전달받은 참조 변수에 새로운 객체를 할당하면, 복사본 참조만 새 객체를 가리키게 되므로 원래 참조 변수에는 변화가 없습니다.
Primitive Type Test
public class PrimitiveType {
public static void main(String[] args) {
int x = 1;
int y = 2;
// before modification
System.out.println(x == 1);
System.out.println(y == 2);
modify(x, y);
System.out.println(x == 1);
System.out.println(y == 2);
}
private static void modify(int x1, int x2) {
x1 = 5;
x2 = 10;
}
}
- stack memory에 저장된 원본의 값은 변동되지 않습니다.
- modify 메서드 호출 후에 생성되는 복사본의 값이 각각 5, 10으로 변동됩니다.
Reference Type Test
Reference Type의 동작과정
- 1번의 경우 A, B 객체 생성 시 stack 메모리에 존재하는 참조 변수가 heap 메모리에 존재하는 각각의 객체를 가리키고 있는 상태입니다.
- 2번의 경우는 modify 메서드 호출 시점에 Call By Value를 통해 참조 변수의 복사본을 생성하여 stack 메모리에 저장합니다.
- 참조 변수의 복사본은 기존의 참조변수와 동일하게 같은 객체를 바라보고 있는 형태입니다.
메서드 내에서 참조 변수가 새로운 객체를 할당할 경우
- 메서드 호출 시 넘겨주는 참조 변수에 대해 새로운 객체를 할당할 경우 힙 메모리에 새로운 객체를 바라보게 되므로 원본 객체에 대해서는 아무런 영향을 미치지 않게 됩니다.
- 위의 명시한 예제와 같은 형태입니다. (modify 메서드 내부에서 새로운 객체를 할당)
<참고 자료>
https://www.baeldung.com/java-pass-by-value-or-pass-by-reference
'CS' 카테고리의 다른 글
[CS] Socket Communication (1) | 2025.09.26 |
---|---|
[CS] Concurrency, Parallelism (0) | 2025.09.24 |
[CS] clustered Index, non-clustered Index (4) | 2025.08.27 |
[Java] Functional Interface (5) | 2025.08.26 |
[CS] JVM Memory Structure (6) | 2025.08.15 |