함수 호출 시 매개변수로 전달받은 인자는 원본 데이터일까요?
우리 자바는 "원본 데이터가아닌 복사한 값을 전달받는 Call by value 방식"을 사용합니다.
예시를 통해 알아봅시다.
public class CallByValue {
public static void toZero(int data) {
data = 0;
}
public static void main(String[] args) {
int data = 100;
System.out.println("호출 전 : " + data); //호출 전 : 100
toZero(data);
System.out.println("호출 후 : " + data); //호출 후: 100
}
}
toZero() 메서드 내에서 원본 데이터를 변경하려 했지만 변경이 되지 않은 모습입니다.
그렇다면 원본 데이터의 훼손이란 불가능한 걸까요?
아닙니다. 값을 전달받더라도 "원본 데이터는 훼손 가능"합니다.
public class CallByValue {
public static class Me {
int data = 100;
}
public static void toZero(Me me) {
me.data = 0;
}
public static void main(String[] args) {
Me me = new Me();
System.out.println("호출 전 : " + me.data); //호출 전 : 100
toZero(me);
System.out.println("호출 후 : " + me.data); //호출 후 : 0
}
}
위와 같이 원본 데이터를 훼손시킬 수 있기 때문에 예전에는 Call by reference 방식이라 주장도 꽤나 존재했습니다.
그렇지만 현재 대부분의 사람들이 자바는 Call by value 방식이다라는 의견에 동의를 합니다.
다음 예시를 보시죠.
public class CallByValue {
public static class Me {
int data;
public Me(int data) {
this.data = data;
}
}
public static void toZero(Me me) {
me = new Me(0);
System.out.println("호출 중(복사 데이터) : " + me.data); //호출 중(복사 데이터) : 0
}
public static void main(String[] args) {
Me me = new Me(100);
System.out.println("호출 전(원본 데이터) : " + me.data); //호출 전(원본 데이터) : 100
toZero(me);
System.out.println("호출 후(원본 데이터) : " + me.data); //호출 후(원본 데이터) : 100
}
}
만일 Call by reference라면 호출 후에도 값이 변경되어 있어야 합니다.
하지만 원본 데이터는 신기하게도 멀쩡합니다.
그 이유는 원본 데이터에 대한 참조를 값으로 전달받았고 해당 변수는 그 참조를 다른 값으로 교체했기 때문입니다.
참조값을 넘기는데 어떻게 Call by reference가 아니냐 하실수 있습니다.
물론 이 논의도 참조를 어떻게 해석하냐에 따라 의견이 갈리고 저 또한 C언어를 먼저 배웠기에 많은 혼란이 있었습니다. 여기서 중요한 점은 "자바에서 참조값을 넘긴다는 말의 의미는 Call by reference에 해당하지 않는다" 정도로 이해하시면 되겠습니다.
참고
https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value
'Java > Grammer' 카테고리의 다른 글
String Class (3) - 정규표현식 (0) | 2022.04.02 |
---|---|
String Class (2) - 주요 메서드 (0) | 2022.03.27 |
String Class (1) - Immutable과 StringBuilder/StringBuffer (0) | 2022.03.26 |
추상클래스와 인터페이스의 차이 (0) | 2022.01.16 |
생성자와 상속의 관계 (0) | 2021.12.25 |