CS/Java

Call by Value & Call by Reference

leah-only 2025. 3. 24. 16:41

Java

자바는 Call by Value 방식을 사용하며 Call by Reference 는 존재하지 않는다. 

 

Call by Value

함수의 인자를 전달할 때 을 전달하는 방식

전달받은 값을 복사하여 처리한다. 전달받은 값을 변경해도 원본은 변경되지 않는다. 

public class CallByValue {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 20;

        System.out.println("Before Call Method : num1 = " + num1 + " , num2 = " + num2);

        method(num1, num2);

        System.out.println("After Call Method : num1 = " + num1 + " , num2 = " + num2);
    }

    public static void method(int num1, int num2) {
        num1 = 30;
        num2 = 40;

        System.out.println("Inside Method : num1 = " + num1 + " , num2 = " + num2);
    }
}

 


Call by Reference

참조에 의한 호출 , 주소를 전달하는 방식

전달받은 값을 직접 참조한다. 전달받은 값을 변경하면 원본도 같이 변경된다. 

public class MyClass {
    int value;

    MyClass(int value){
        this.value = value;
    }

    public static void swap(MyClass x, MyClass y) {
        int tmp = x.value;
        x.value = y.value;
        y.value = tmp;
    }

    public static void main(String[] args) {
        MyClass num1 = new MyClass(10);
        MyClass num2 = new MyClass(20);

        System.out.println("Before Call Method : num1 = " + num1.value + " , num2 = " + num2.value);

        swap(num1, num2);

        System.out.println("After Call Method : num1 = " + num1.value + " , num2 = " + num2.value);
    }
}

 


 

⁉️ Java에서 Call by Reference는 없다?

자바에는 데이터 타입이 2가지가 있다. 

  • 기본형 : boolean, short, int, long, float, double, char
  • 참초형 : Class, Interface, Array, Enum 등 기본형을 제외한 모든 것들 (Integer, Object, Map)
public class MyClass {
    public static void main(String[] args) {

        int var = 1;
        int[] arr = {1};

        // call by value
        add_value(var);
        System.out.println("기본형 : " + var);

        // call by reference
        add_reference(arr);
        System.out.println("참조형 : " + arr[0]);
    }

    public static void add_value(int var1) {
        var1 += 100;
    }

    public static void add_reference(int[] arr1) {
        arr1[0] += 100;
    }
}

 

왜 둘의 값이 다를까? 

기본형은 stack의 변수 안에 value를 저장한다. 

참조형은 stack의 변수 값에는 객체의 주소 값, 객체는 별도의 Heap 영역에 저장한다. 

  • 기본형 : stack에 값이 저장된다. 
  • 참조형 : stack에 주소값이 저장되고, Heap 영역에 실제 데이터가 저장된다. 

  • add_value 내 var1가 바뀐것 → var가 바뀐게 아니다. 

  • arr와 arr1은 같은 주소 값을 가진다. → 두 변수가 하나의 데이터를 동시에 참조 

이렇게 보면 call by reference가 아닌가 생각이 들 수 있다. 

그러나 Java는 C와 다르게 포인터를 철저하게 숨겨 개발자가 직접 메모리에 접근하지 못하게 했기 때문에 call by reference라는 개념이 존재하지 않는다. 

즉, call by value로 동작하면서 원시값이 복사되느냐 주소값이 복사되느냐의 차이다. 

 

call by reference 라면 두 변수가 완전히 같아야 하는데 

위에서 add_reference() 호출 시 arr의 주소값을 담아 새로운 변수 arr1를 선언한다. 이는 단순히 주소값의 복사이다. 

두 변수는 같은 주소를 가지고 있을 뿐 서로 다른 scope에 존재하여 별도로 분리되어 존재한다. 


✅ Q2. 자바에는 포인터 개념이 없는 이유

자바는 안전성과 단순성을 중시하는 언어이기 때문에 C/C++처럼 직접적인 포인터 조작을 금지했다. 

  • 메모리 안전성 확보
    • 포인터는 임의 메모리 접근이 가능해 보안상 위험이 크다 (ex. 버퍼 오버플로우)
  • GC 사용
    • 자바는 개발자가 직접 메모리를 해제할 필요 없도록 설계되어 있어 포인터가 불필요하다. 
  • 복잡도 감소
    • 포인터 문법은 어렵고 실수하기 쉽다. 자바는 객체 참조로 간결하게 처리한다. 

→ 자바는 객체에 대한 참조를 이용해 포인터와 유사한 효과를 안전하게 제공한다. 


✅ Q3. C++의 Call by Reference vs Java의 Reference 차이점

🔍 항상 Java는 Call by Value 라는 점을 기억하자!!

  C++의 Call by Reference Java의 Reference
호출 방식 Call by Reference (주소 전달) Call by Value (참조값 복사)
원본 수정 가능 (참조로 직접 접근) 객체 내부 값은 수정 가능하지만, 참조 자체는 변경 불가
예시 의미 함수 내에서 참조값 자체를 바꿀 수 있음 참조값은 복사되므로 바꿔도 원본에 영향 없음

 

🔁 C++ (Call by Reference)

void change(int& x) {
    x = 10; // 원본 값 자체 변경
}

 

🔁 Java (Reference 전달은 Call by Value)

void change(MyObj obj) {
    obj = new MyObj(); // obj 참조는 바뀌지만 원본에는 영향 없음
}

 

but, 내부 값을 바꾸면? 

void change(MyObj obj) {
    obj.value = 10; // 내부 필드는 변경됨 (같은 참조니까)
}

 

🔑 정리

  • Java는 참조값 자체를 복사해서 전달 (Call by Value)
  • C++은 진짜 Call by Reference를 지원해서 변수 자체를 바꿀 수 있음 

참고 : https://github.com/devFancy/2023-CS-Study/blob/main/java/java_call_by_value.md

'CS > Java' 카테고리의 다른 글

Boxing & UnBoxing  (0) 2025.03.28
Mutable & Immutable  (0) 2025.03.26
Xms, Xmx  (0) 2025.03.21
JDK / JRE  (0) 2025.03.21
JVM (Java Virtual Machine)  (1) 2025.03.13