자바는 항상 Call-By-Value(Pass-By-Value)로만 동작한다고 한다.
분명 자바를 처음 배울때는 Call-By-Value와 Reference-By-Value를 모두 사용한다고 배웠던거 같은데 어떻게 된건지 알아보겠다.
(Call-By-Value와 Pass-By-Value에서 Call과 Value는 거의 동일하게 사용한다고 하니 Call-By-Value로 통일하여 작성하기로 한다.)
일단 처음 Call-By-Value와 Reference-By-Value를 학습할 때 배우는 swap 예제를 살펴본다.
아래는 Call-By-Value의 예시로 작성된 코드이다.
a,b 변수를 swap 함수의 인자로 건네줘서 값을 바꿨지만 a, b 변수의 값은 그대로이다. 즉, a, b의 값만 복사(Call-By-Value)하여 x, y 변수가 지역변수로 새로 생성됐기 때문에 x와 y를 스왑하던, 값을 바꾸던 a, b 변수에는 영향이 없는 것이다.
public class CallByTest {
@Test
public void callbyvalue(){
int a = 10;
int b = 20;
System.out.println("swap() 호출 전 : a = " + a + ", b = " + b); // a = 10, b = 20
swap(a, b);
System.out.println("swap() 호출 후 : a = " + a + ", b = " + b); // a = 10, b = 20
}
public void swap(int x, int y){
int temp = x;
x = y;
y = temp;
}
}
그럼 Call-By-Reference 예제로 배웠던 swap 예제코드를 살펴본다.
swap 호출전후로 인자로 넘겼던 객체의 상태값이 바꼈으므로 Call-By-Reference의 예시로 알았던 코드이다.
public class CallByTest {
@Test
public void CallByReference(){
Game a = new Game(10);
Game b = new Game(20);
System.out.println("swap() 호출 전 : a.star = " + a.star + ", b.star = " + b.star); // a.star = 10, b.star = 20
swap(a, b);
System.out.println("swap() 호출 후 : a.star = " + a.star + ", b.star = " + b.star); // a.star = 20, b.star = 10
}
public void swap(Game x, Game y){
int temp = x.star;
x.star = y.star;
y.star = temp;
}
class Game {
int star;
public Game(int star) {
this.star = star;
}
}
}
하지만, 진정한 Call-By-Reference는 참조하는 객체의 상태값을 변경하는게 아니라 실제 x,y 변수가 참조하는 객체를 변경하여 외부의 a 변수가 참조하는 객체를 바꿀수 있는 경우를 말한다.
자바는 Call-By-Value만 지원하므로 아래 코드에서는 a가 참조하는 객체가 realCallByReference() 함수에서 변경한 객체(star 값이 20인)로 변경되지 않고 여전히 10이 출력되는 걸 볼 수있다.
public class CallByTest {
@Test
public void test(){
Game a = new Game(10);
realCallByReference(a);
System.out.println("a가 참조하는 객체는 바뀌지 않음 : " + a.star); // 10
}
public void realCallByReference(Game x){
x = new Game(20);
}
}
1. 함수 내에서 지역변수 x가 새로 생성되며 함수인자인 a와 같은 객체를 참조함.
> Call-By-Value에 의해 a가 참조하는 객체에 대한 위치값만 전달해줬음.
2. realCallByReference 함수내에서 x가 참조하는 객체를 신규로 생성한 객체로 변경함.
> a와 같은 객체를 참조하다가 새로운 객체로 변경되었으며 a에는 전혀 영향없음.
3. realCallByReference 함수 종료후 출력결과를 보면 a는 그대로 기존 객체를 참조하고 있음.
정리해보면
자바는 Call-By-Value만을 지원한다.
처음 학습시 Call-By-Reference의 예제로 알고있던 swap코드는 참조하는 객체의 상태값을 바꾸는 것이지 참조하는 객체 자체를 바꾸는 것이 아니므로 진정한 Call-By-Reference의 예제는 아니다.
참고 StackOverflow
stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value
'개발 > JAVA' 카테고리의 다른 글
String 생성자(생성자 종류 및 예시) (0) | 2020.12.12 |
---|---|
Java 콘솔에서 값 읽기(BufferedReader, Scanner, Console) (0) | 2020.12.11 |
Java string 비교(==와 equals 메서드 그리고 String.intern()) (0) | 2020.12.10 |
NullpointerException 과 해결법 (0) | 2020.12.09 |
[Java 기본] Java Primitive 데이터 타입 (0) | 2020.12.09 |