메소드의 파라미터 전달 방식에는 Call by Value
와 Call by Reference
두 가지 방식이 있다.
Call by value
는 메소드의 파라미터로 변수의 값
을 복사해서 전달하는 방식이다.
즉, 원래의 값에 영향을 주지 않고 함수 내로 복사된 값
을 전달하며, 값을 복사하기 때문에 변수의 크기가 클수록 비용이 증가하게 된다.
Call by Reference
는 메소드의 파라미터로 변수의 주소
를 전달하는 방식이다.
즉, 변수의 주소를 전달하기 때문에 원래 변수의 값에도 영향을 줄 수 있다.
아래 예제 코드
2개를 통해 Java의 파라미터 전달 방식을 살펴보겠다.
public class CallByReferenceExample {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println("Before calling modifyArray method: "
+ Arrays.toString(arr));
modifyArray(arr);
System.out.println("After calling modifyArray method: "
+ Arrays.toString(arr));
}
public static void modifyArray(int[] arr) {
arr[0] = 0;
arr[1] = 0;
arr[2] = 0;
}
}
위 코드에서는 세 개의 요소로 배열
을 만들고, modifyArray 메소드
에 전달 후, modifyArray 메소드
내부에서 배열
의 요소를 0으로 수정한다. 메소드 호출 전후에 배열 내용을 인쇄하면 메소드 내부에서 수정한 내용도 원래 배열에 영향을 미쳤음을 알 수 있다.
실행 결과 :
Before calling modifyArray method: [1, 2, 3]
After calling modifyArray method: [0, 0, 0]
modifyArray 메소드는
main 메소드 arr
배열과 같은 메모리에 접근한다.
여기까지만 보면 마치 Call by Reference
인 것 처럼 보인다.
이제 다음 예제 코드를 보겠다.
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
modifyStringBuilder(sb);
System.out.println(sb.toString()); // prints "Hello, world!"
}
public static void modifyStringBuilder(StringBuilder sb) {
sb.append(", world!");
sb = null; // main()의 변수에 영향을 주지 않는다.
}
이 코드에서는 StringBuilder
객체를 modifyStringBuilder 메서드
에 전달한다.
메서드 내에서 StringBuilder
객체에 ", world!"
를 추가하여 객체를 수정한다.
그 후 sb
매개 변수를 null
로 설정하며 참조 변경을 시도한다.
그러나 실제로는 main 메소드
의 sb
에는 영향을 주지 않는 것을 알 수 있다.
자바에서는 개발자가 직접 메모리 주소에 접근 할 수 없다.
파라미터의 전달은 원시값
이 복사 되느냐 주소값
이 복사되느냐의 차이가 있으며,
원시값
인 경우 바로 연산을 수행하고, 주소값
인 경우 해당 메모리 주소를 참조하여 값을 가져와
연산을 수행하거나 저장할 수 있다. 그러나 참조 대신 다른 객체를 할당하여도 원본을 변경 할 수 없다.
즉, 변수가 가르키는 객체의 주소를 전달 받았을 뿐, 변수가 다른 값(객체)을 가르키도록 변경 할 수는 없다.