안녕하세요. 이번에 작성한 내용은 값 전달 방식(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 객체는 참조로 전달되었기 때문에 메소드 실행 후에도 값이 그대로 남아있는 것을 보실 수 있습니다.
'프로그래밍 > Java 기초' 카테고리의 다른 글
자바 제네릭(Generics)과 컬렉션(Collections) (0) | 2017.11.27 |
---|---|
어노테이션(Annotation) (0) | 2017.10.13 |