Java는 Call By Value와 Call By Reference중
Call By Value라는 사실은 너무 유명한 사실이다.
이를 좀더 정확히 이해해보고 싶었는데,
우선 call by value와 call by reference의 차이점을 알아보자.
Call by value(값에 의한 호출)는 인자로 받은 값을 복사하여 처리를 한다. Call by reference(참조에 의한 호출)는 인자로 받은 값의 주소를 참조하여 직접 값에 영향을 준다. 간단히 말해 값을 복사를 하여 처리를 하느냐, 아니면 직접 참조를 하느냐 차이다.
코드를 보면 이해하기 쉬웠다.
public class Main {
public static void main(String[] args) {
int a = 1;
System.out.println(a);
method(a);
System.out.println(a);
}
public static void method(int a){
a = 2;
}
}
결과는 다음과 같다.
1
1
call by reference였을 경우 a의 값은 2로 나왔겠지만
자바는 call by value이니 당연히 1로 나왔다.
여기까지는 고개를 상당히 끄덕이며 오케이.
그렇다면 인스턴스를 파라미터로 받았을 경우는 어떨까.
public class Main {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.a);
method(person);
System.out.println(person.a);
}
public static class Person{
int a = 1;
}
public static void method(Person person){
person.a = 2;
}
}
1
2
값이 변경됐다.
여기서부터 헷갈리기 시작할 수 있었다.
Java는 분명 call by value라고 하지 않았나?
왜 값이 변경됐을까
참조변수의 개념을 이해하고 있다면 쉽게 납득할 수 있을 것이다.
참조 변수에 들어있는 실제 값은 heap 메모리 영역에 주소값을 가지고 있기에 주소값을 카피하게 되고 결과적으로 같은 주소값을 가르키게 되는데, 파라미터로 받아온 변수에 다른 인스턴스를 할당한다면 기존 값은 변경이 없겠지만 받아온 상태로 (같은 주소를 가르키고 있는 상태로) 메모리에 저장되있는 인스턴스를 수정한다면 결과적으로 같은 주소를 가르키고있던 인스턴스가 변하게 되는 것이다.
그렇다면 여기서 또 다른 참조변수, Integer를 통해 차이를 봐보자.
public class Main {
public static void main(String[] args) {
Integer a = 333;
Integer b = 555;
System.out.println(a+" "+b);
method(a,b);
System.out.println(a+" "+b);
}
public static void method(Integer a, Integer b){
a = 10;
b = 20;
}
}
결과는 다음과 같다.
333 555
333 555
이상하다. 어째서 같은 참조변수인데 결과값이 변하지 않았을까?
이또한 처음에는 이상하다 싶었는데
얼마안가 이해됐다.
파라미터로 받아온 변수는 같은 주소를 가르키고 있을 뿐 서로 다른 변수이다.
파라미터로 받아온 변수의 주소값을 변경했을 뿐 기존 메소드 밖에 있던 변수의 주소값이 변경된 것은 아니기 때문에 기존 변수에는 영향이 없는 것이다.
헷갈릴만하지만 이로서 좀더 call by value를 이해할 수 있었던 듯 하다.
참조
https://velog.io/@ahnick/Java-Call-by-Value-Call-by-Reference