Call By Value와 Call By Reference
특정 메서드를 호출하는 경우 인자로 전달하는 방법은 크게 2가지가 존재하는데요. 값에 의한 호출(Call By Value), 참조에 의한 호출(Call By Reference)이 이에 해당됩니다.
값에 의한 호출(Call By Value) 은 메서드를 호출할 때, 값 자체를 넘겨주는 방식입니다. 메서드를 호출하는 함수의 변수와 호출된 함수의 파라미터는 서로 다른 변수입니다.
반면, 참조에 의한 호출은(Call By Reference) 는 메서드를 호출할 때, 참조를 직접 전달하는 방식입니다. 참조를 직접 전달하기 때문에 호출하는 함수의 변수와 호출된 함수의 파라미터는 동일한 변수입니다. 따라서, 파라미터를 수정하는 경우 그대로 원본에도 영향을 미칩니다.
✔️ 자바는 어떤 방식을 채택할까? 🤔
자바는 값에 의한 호출(Call By Value)만 존재합니다.
자바의 변수는 스택 영역에 할당됩니다. 이때, 변수의 타입이 원시 타입인 경우에는 값 또한 스택 영역에 저장됩니다. 그리고, 참조 타입인 경우 객체 자체는 힙 영역에 저장되고 스택 영역에 존재하는 변수가 객체의 주소를 가지고 있습니다.
만약 특정 메서드에 원시 타입의 변수를 인자로 전달하여 호출하면, 호출된 메서드의 해당 파라미터가 변경되어도 원본은 수정되지 않습니다. 왜냐하면, 호출된 메서드의 스택 프레임에 인자로 주어진 변수의 값이 복사되어 사용되기 때문입니다.
반면, 참조 타입의 변수를 인자로 전달하여 호출하는 경우에는 호출된 메서드 내부에서 원본이 수정될 수 있습니다. 하지만, 이러한 방식은 호출된 메서드의 스택 프레임에 참조 타입 변수를 중복하여 생성하기 때문에 값에 의한 호출로 판단됩니다. 가령, 다음과 같은 코드가 존재할 때, foo 메서드의 스택 프레임과 var 메서드의 스택 프레임에 각각 같은 student 객체의 주소를 가지고 있는 참조 타입 변수인 student가 존재합니다.
public void foo() {
Student student = new Student();
var(student);
}
public void var(Student student) {
student.study();
}