일반적으로 자바의 primitive type을 파라미터로 전달 시, 값에 의한 호출이 일어난다.
public class CallByValue {
public static void main(String[] args) {
var callByValue = new CallByValue();
int before = 10;
int after = 15;
System.out.println("Before Change : " + before);
callByValue.changeValue(before, after);
System.out.println("After Change : " + before);
}
void changeValue(int target, int toChange) {
target = toChange;
System.out.println("In Change : " + target);
}
/* 출력 결과
Before Change : 10
In Change : 15
After Change : 10
*/
}
위 예제를 보면 알 수 있듯이, primitive type은 changeValue 함수는 before 변수의 값을 바꿀 수 없다. 이는, changeValue() 메서드 호출 시, 스택 프레임이 생성되고, 파라미터의 값을 직접 복사하여, 새로운 메모리에 할당된다. 따라서, 실제 before의 값의 변화는 없다.
일반적으로 자바의 클래스(참조 타입)을 파라미터로 전달 시, 주소 값을 복사하여 전달한다.
public class CallByReference {
public static void main(String[] args) {
CallByReference callByReference = new CallByReference();
int before = 10;
int after = 15;
TestClass testClass = new TestClass(before);
System.out.println("[Before]" + testClass + " : " + testClass.value);
callByReference.changeValue(testClass, after);
System.out.println("[After]" + testClass + " : " + testClass.value);
}
void changeValue(TestClass testClass, int toChange) {
testClass.value = toChange;
System.out.println("[In Change]" + testClass + " : " + testClass.value);
}
static class TestClass {
int value;
public TestClass(int value) {
this.value = value;
}
}
}
/* 출력결과
[Before]org.example.CallByReference$TestClass@1 : 10
[In Change]org.example.CallByReference$TestClass@1 : 15
[After]org.example.CallByReference$TestClass@1 : 15
*/
위 예제를 보면, changeValue 메서드 호출시, 실제 값이 변경되는 것을 볼 수 있다.
모든 클래스는 Object를 상속받으므로, Object의 toString() 메서드를 살펴보면 다음과 같다.
기본적으로, toString()을 오버라이딩하지 않으면, {className}@{hashcode}로 리턴되는 것을 알 수 있습니다. 따라서, changeValue 메서드에서는 파라미터로 전달된 참조 타입은 해당 주소 값을 복사하여, 객체를 참조합니다. 최종적으로 결과가 바뀐 것을 알 수 있습니다.