자바에서 call by reference는 c에서 포인터의 개념과 비슷하다 하지만 실제 call by reference로 동작하는 건 아니다!
call by reference와 비슷한지만 실제로는 call by reference가 아니라고????
거두절미하고 아래 코드를 살펴보자
public class Test {
public static void main(String[] args) {
Human me = new Human();
me.age = 10;
addAge(me);
System.out.println("addAge method -> " + me.age);
setNull(me);
System.out.println("setNull method -> " + me.age);
setName(me);
System.out.println("setName method -> " + me.name);
}
public static void addAge(Human h) {
h.age = h.age + 5;
}
public static void setNull(Human h) {
h = null;
}
public static void setName(Human h) {
h.name = "Terry";
}
}
class Human {
String name;
int age;
}
age프로퍼티를 10으로 갖고있는 me 객체를 만들어준다음
1. age를 5살 더해주는 addAge 메서드
2. null로 만들어주는 setNull 메서드
3. name 프로퍼티를 설정해 주는 setName 메서드
를 차례로 실행시켜줬고 콘솔창에 출력 결과를 확인해 보면 다음과 같다.
여기서 우리가 눈여겨 봐야할 메서드는 두 번째로 실행시켜 준 setNull메서드이다.
분명히 실매개변수로 넣어준 me객체의 레퍼런스를 넘겨줬고 직접 null을 할당해 줬음에도 불구하고 정상적으로 me객체의 age프로퍼티가 출력되고 심지어 그 이후에 실행시켜 준 setName메서드로 name 프로퍼티도 정상적으로 할당되었음을 알 수 있다.
뭔가 이상하지 않은가? Call by reference 로 동작했다면 참조를 직접 넘기기 때문에 메서드 내에서 파라미터를 수정하면 그대로 원본에도 반영되어야 함에도 불구하고 setNull메서드가 생각한 대로 동작하지 않았음을 알 수 있다.
사실 me 랑 메소드의 실매개변수로 전달되는 me 서로 다른 존재이다 실매개변수로 전달되는 me를 설명을 위해 임의로 me2라고 부르겠다.
me2는 me가 가리키고 있는 힙영역에 있는 Human 객체를 똑같이 가리키고 있는 복사된 존재이다.
me2와 me는 둘 다 Human객체를 가리키고 있어 age를 더하는 행위나 name을 설정하기 위해 프로퍼티에 접근이 가능하지만 me2에 null을 할당해 버리면 단지 me2가 가리키고 있는 Human객체와의 연결고리를 끊어버리는 것과 같은 행위에 불과하지 Human객체 자체에 null을 할당한 것이 아니다.
결론
따라서 java는 call by reference로 동작하지 못하며 오직 call by value만 존재함을 알 수 있다.