Call By Value vs Call By Reference

MyeongJae Lee·2022년 1월 18일
0

Call By Value와 Call By Refernce를 생각해야 하는 경우는 매개변수를 가지고 있는 메서드를 호출하는 경우다.

call by value

public void callByValue(int value) { 
	value = 100;
}

위 메서드는 primitive type인 int를 매개변수로 갖고 있다. 이 때 다음 코드를 보자.

int number = 1;

callByValue(number);

callByValue() 메서드 실행 후, number 변수에는 어떤 값이 들어있을까?
답은 1이다.

매개변수의 number는 1이라는 '값'을 복사해서 callByValue() 메서드로 전달한다. 따라서 메서드 안에서 변경한 number라는 변수는 복사본을 수정한 것이다.

call by reference

다음과 같이 reference type의 Box class가 있다.

class Box {
	int number;
}

또한 Box class를 매개변수로 갖는 callByReference() 메서드를 생각해보자.

public void callByReference(Box box) {
	box.number = 100;
}

그리고 다음 코드를 보자.

Box box = new Box();
box.number = 1;

callByReference(box);

callByReference() 메서드 실행 후, box 인스턴스의 number 변수에는 어떤 값이 들어있을까?
답은 100이다.

매개변수의 box에는 box 인스턴스의 '주소(reference)'를 callByReference() 메서드로 전달한다. 따라서 메서드 안에서 box 인스턴스를 변경하면, 전달받은 매개변수의 복사본이 아닌 원본을 수정하는 것이다.

그렇다면?

public void test(String str) {
	str = "update";
}

위와 같이 reference type의 String을 매개변수로 갖는 test() 메서드를 생각해보자.

String status = "not update";

test(status);

test() 메서드 실행 후, status 변수에는 어떤 값이 들어있을까?
답은 "not update"이다.

String은 메서드에게 분명 주소를 넘겨줄텐데, 왜 call by reference로 동작하지 않고 call by value로 동작할까?

이유는 String은 final class이기 때문이다. test() 메서드 내부의 str = "update";는 str 주소의 인스턴스를 변경하는 것이 아니라, "update"라는 문자열로 된 새로운 인스턴스를 생성하는 것이다.

따라서 test() 메서드 내부에서 선언된 "update"라는 문자열의 인스턴스는 test() 메서드 외부에서는 접근할 수 없다.

Integer 등의 wrapper class도 final class로 String와 같다.

ps

call by reference의 예시 코드에서 메서드의 return type을 void로 선언하였다. 하지만 'Clean Code'의 원칙에 따라 return type을 void가 아닌 Box로 하는 것이 좋다.

profile
개발자가 하고싶어요

0개의 댓글