메소드의 파라미터를 전달하는 방식에는 두 가지 방식이 있다.
call by value
: 파라미터에 전달할 때 값만 복사하여 전달한다. 파라미터를 호출할 때 입력했던 값과 메소드 내부에서 사용하는 값의 참조값은 다르다.call by reference
: 파라미터에 전달할 때 참조값을 복사하여 전달한다. 값을 복사하였지만 복사된 값이 실제 값의 주소값을 가리키므로, 파라미터를 호출할 때 입력했던 값의 주소와 메소드 내부에서 사용하는 값의 주소가 같다. 즉, 변경에 영향을 받는다.자바에서 사용하는 전달 방식은 call by value
로 메소드 내부에서 전달받은 값과 외부의 값은 영향을 미치지 않는다.
public static void main(String[] args) {
int test = 0;
raiseIntBy(test, 3);
System.out.println(test); // 0
}
public static void raiseIntBy(int x, int y){
x += y;
}
다만, 자바에서는 자료형 타입이 두 가지가 있다. 위의 예시처럼 원시자료형(primitive type) 의 경우에는 영향이 없으나 객체를 전달할 때는 객체의 주소값을 전달한다.
// Person 객체를 설계해보자
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// Test 클래스에서 객체를 사용해보자
public class Test {
public static void main(String[] args) {
Person p = new Person("Jason", 22);
System.out.printf("Name: %s, Age: %d \\n", p.getName(), p.getAge());
// Name: Jason, Age: 22
changeName(p, "Eva");
changeAge(p, 33);
System.out.printf("Name: %s, Age: %d \\n", p.getName(), p.getAge());
// Name: Eva, Age: 33
Person q = new Person("David", 45);
System.out.printf("Name: %s, Age: %d \\n", q.getName(), q.getAge());
// Name: David, Age: 45
swap(p, q);
System.out.printf("Name: %s, Age: %d \\n", p.getName(), p.getAge());
// Name: Eva, Age: 33
System.out.printf("Name: %s, Age: %d \\n", q.getName(), q.getAge());
// Name: David, Age: 45
}
public static void changeName(Person s, String newName) {
s.setName(newName);
}
public static void changeAge(Person s, int a) {
s.setAge(a);
}
private static void swap(Person a, Person b) {
Person temp = a;
a = b;
b = a;
}
}
changeName()
나 changeAge()
처럼 객체를 입력받는 메소드는 메소드 내부에서 객체의 주소값을 전달받았기 때문에 변경사항이 적용된다.
하지만 swap()
메소드의 동작은 두 인스턴스의 주소값이 변경될거라 기대했으나 실제로는 그렇지 않았다. swap()
메소드의 동작은 다음과 같다.
a
변수에 p
의 주소값이 복사된다.b
변수에 q
의 주소값이 복사된다.temp
변수에 a
의 주소값을 대입한다.a
와 b
의 값을 변경한다.swap()
메소드의 내부에서 사용하던 a
와 b
의 참조값은 바뀌었지만 그저 내부 변수의 값이 변한 것일뿐 메소드 외부의 값에는 영향이 없다. 그럼 다시 changeName()
의 동작을 보자.
s
변수에 p
의 주소값이 복사된다.
s
와 p
는 같은 주소값을 가지고 있다.s
의 setName()
을 호출하여 값을 변경한다.
s
와 p
가 가리키는 객체 주소값이 일치하여 본래의 p
객체의 값이 변경된다.