프로그래밍/Java 기초

값 전달 방식(Call by value, Call by reference)

수니모스 2017. 11. 30. 17:52

 안녕하세요. 이번에 작성한 내용은 값 전달 방식(Call by value, Call by reference)에 대한 내용입니다.


 코드를 작성하다보면 여러가지 메소드나 변수를 통해서 값을 주고 받으며 사용하게 됩니다. 그 때 메소드나 변수에 값이 전달되는 방식이 나뉘게 됩니다. 흔히 Call by value, Call by reference라고 부르는 것들이 그것이죠. 쉽게 설명하자면 Call by value는 값 자체를 전달하는 것이고 Call by reference는 참조해서 사용하도록 연결해주는 것입니다.

 자바에서는 이 부분이 매우 쉽게 되어있습니다. 기본 형식(primitive type)으로 된 변수는 Call by value, 객체(Object)로 되어있는 것들은 Call by reference로 동작합니다. 아래의 코드를 보시죠.


1. ReferenceObject 형식 정의

package com.tistory.sunimohs;

public class ReferenceObject {
  public int value = 0;
}

2. 화면을 표시할 MainClass 정의

package com.tistory.sunimohs;

public class MainClass {
  public static void main(String[] args) {
    printStudy1();
    
    printStudy2();
  }
  
  public static void printStudy1() {
    int value1 = 0;
    int value2 = value1;
    
    ReferenceObject object1 = new ReferenceObject();
    ReferenceObject object2 = object1;
    
    value1 = 5;
    object1.value = 5;
    
    System.out.println("print study1 start");
    
    System.out.println("value1 : " + value1);
    System.out.println("value2 : " + value2);
    
    System.out.println("object1.value : " + object1.value);
    System.out.println("object2.value : " + object2.value);
    
    System.out.println();
  }
  
  public static void printStudy2() {
    int value = 0;
    ReferenceObject ro = new ReferenceObject();
    
    System.out.println("print study2 start");
    
    System.out.println("value : " + value);
    System.out.println("reference object value : " + ro.value);
    callByValue(value);
    callByReference(ro);
    System.out.println("value : " + value);
    System.out.println("reference object value : " + ro.value);
  }
  
  public static void callByValue(int value) {
    value = 5;
    
    System.out.println("callByValue value : " + value);
  }
  
  public static void callByReference(ReferenceObject referenceObject) {
    referenceObject.value = 5;
    
    System.out.println("callByReference value : " + referenceObject.value);
  }
}


 위의 코드에서 printStudy1 메소드부터 살펴보도록 하죠. printStudy1 메소드에서 int 형 value1에 0값을 할당하고 value2에 value1을 할당합니다. 이 때 값 전달 방식은 기본 형식(primitive type)이기 때문에 Call by value와 같이 동작합니다. 값만 전달되는 방식이죠. 그 다음 ReferenceObject 형식 object1을 생성합니다. object2에 object1을 할당합니다. 이 때 전달 방식은 Call by reference와 같이 동작합니다. 아래는 printStudy1의 결과입니다.


print study1 start
value1 : 5
value2 : 0
object1.value : 5
object2.value : 5

 순서대로 value1, value2, object1의 value, object2의 value를 출력하였습니다. 여기서 이상한 것을 보실 수 있는데요. value1과 value2가 값이 다르다는 것입니다. value2에는 value1을 할당하였으나 값만 전달되었기 때문에 value1에 5를 할당하여도 value2에는 변화가 없고 object2에는 동일한 방식으로 object1을 할당하였으나 값 참조로 전달하였기 때문에 같이 바뀌게 된 것입니다.

 엄밀하게 말하면 '같이 바뀌었다.'라는 것은 맞지 않고 object1.value만 바뀌고 object2.value는 object1.value를 바라본다고 할 수 있겠네요. 값 참조라고 하면 뭔가 어려운 말로 들릴 수 있는데요. 이렇게 생각하시면 쉽습니다. object1에만 new ReferenceObject()를 통해 새로운 객체를 생성하였고 object2는 그 객체를 빌려서 사용하고 있다고요.


 마찬가지로 printStudy2도 동작 방식이 비슷합니다. 바뀐건 변수에 전달하느냐 메소드의 인자로 전달하느냐의 차이입니다. printStudy2의 결과를 보시죠.

print study2 start
value : 0
reference object value : 0
callByValue value : 5
callByReference value : 5
value : 0
reference object value : 5

int 형 value를 callByValue 메소드의 인자로 보내고 메소드 내부에서 value에 5를 할당합니다. 결과 화면에서도 보이듯이 메소드 내부에서는 5가 표시됩니다. ReferenceObject 형 ro를 callByReference 메소드의 인자로 보내고 메소드 내부에서 인자로 온 ReferenceObject형 객체에 값을 할당합니다. 2개의 메소드 실행 후 메소드에 인자로 보냈던 값을 각각 출력하였습니다. 여기서도 위와 비슷한 현상을 보실 수 있습니다. callByValue 메소드의 인자로 보내진 value는 값만 전달되었기 때문에 메소드 내부에서 변경된 값이 밖까지 적용되지 않습니다. 이와 반대로 ro 객체는 참조로 전달되었기 때문에 메소드 실행 후에도 값이 그대로 남아있는 것을 보실 수 있습니다.


 

ReferenceStudy.zip


'프로그래밍 > Java 기초' 카테고리의 다른 글

자바 제네릭(Generics)과 컬렉션(Collections)  (0) 2017.11.27
어노테이션(Annotation)  (0) 2017.10.13