메서드를 호출할 때 파라미터를 전달하는 방법
Call by Value 는 메서드를 호출할 때 값을 넘겨주기 때문에 Pass by Value 라고도 함
메서드를 호출하는 호출자 (Caller) 의 변수와 호출 당하는 수신자 (Callee) 의 파라미터는 복사된 서로 다른 변수
값만을 전달하기 때문에 수신자의 파라미터를 수정해도 호출자의 변수에는 아무런 영향이 없음
Call by Reference 는 참조 (주소) 를 직접 전달하며 Pass By Reference 라고도 함
참조를 직접 넘기기 때문에 호출자의 변수와 수신자의 파라미터는 완전히 동일한 변수
메서드 내에서 파라미터를 수정하면 그대로 원본 변수에도 반영
Java 에서 변수를 선언하면 Stack 영역에 할당됨
원시 타입 (Primitive Type) 은 Stack 영역에 변수와 함께 저장
참조 타입 (Reference Type) 객체는 Heap 영역에 저장되고 Stack 영역에 있는 변수가 객체의 주소값을 갖고 있음
원시 타입은 Stack 영역에 위치
메서드 호출 시 넘겨받는 파라미터들도 원시 타입이라면 Stack 영역에 생성됨
public class PrimitiveTypeTest {
@Test
@DisplayName("Primitive Type 은 Stack 메모리에 저장되어서 변경해도 원본 변수에 영향이 없다")
void test() {
int a = 1;
int b = 2;
// Before
assertEquals(a, 1);
assertEquals(b, 2);
modify(a, b);
// After: modify(a, b) 호출 후에도 값이 변하지 않음
assertEquals(a, 1);
assertEquals(b, 2);
}
private void modify(int a, int b) {
// 여기 있는 파라미터 a, b 는 이름만 같을 뿐 test() 에 있는 a, b 와 다른 변수
a = 5;
b = 10;
}
}
위 코드에서 test() 의 변수 a, b 와 modify(a, b) 로 전달받은 파라미터 a, b 의 이름과 값은 같지만 다른 변수
modify(a, b) 를 호출하는 순간 Stack 영역에 새로운 변수 a, b 가 새로 생성되어 총 4 개의 변수가 존재
Stack 내부에 test() 와 modify() 라는 영역이 나뉘어져 있고 거기에 동일한 이름을 가진 변수 a, b 가 존재
그래서 modify() 영역의 값을 바꿔도 test() 영역의 변수는 변화가 없음
원시 타입의 전달은 값만 전달하는 Call by Value 로 동작
참조 타입에서 변수 자체는 Stack 영역에 생성되지만 실제 객체는 Heap 영역에 위치
그리고 Stack 에 있는 변수가 Heap 에 있는 객체를 바라보고 있는 형태
class User {
public int age;
public User(int age) {
this.age = age;
}
}
public class ReferenceTypeTest {
@Test
@DisplayName("Reference Type 은 주소값을 넘겨 받아서 같은 객체를 바라본다" +
"그래서 변경하면 원본 변수에도 영향이 있다")
void test() {
User a = new User(10);
User b = new User(20);
// Before
assertEquals(a.age, 10);
assertEquals(b.age, 20);
modify(a, b);
// After
assertEquals(a.age, 11);
assertEquals(b.age, 20);
}
private void modify(User a, User b) {
// a, b 와 이름이 같고 같은 객체를 바라본다.
// 하지만 test 에 있는 변수와 확실히 다른 변수다.
// modify 의 a 와 test 의 a 는 같은 객체를 바라봐서 영향이 있음
a.age++;
// b 에 새로운 객체를 할당하면 가리키는 객체가 달라지고 원본에는 영향 없음
b = new User(30);
b.age++;
}
}
원시 타입 코드와 마찬가지로 동일한 변수 a, b 가 존재
여기서 modify(a, b) 를 호출한 후에 a.age 의 값이 변경되었기 때문에 Call by Reference 로 파라미터를 넘겨주었다고 착각하기 쉽지만
Reference 자체를 전달하는 게 아니라 주소값만 전달해주고 modify() 에서 생긴 변수들이 주소값을 보고 객체를 같이 참조하는 것
Call by Reference 는 참조 자체를 넘기기 때문에 새로운 객체를 할당하면 원본 변수도 영향을 받는 반지만 자바에서는 호출자 변수와 수신자 파라미터가 Stack 영역 내에서 각각 존재하는 다른 변수이므로
자바에서는 Call by Value로 동작