call by value ? call by reference
자료 구조를 배우면서 call by value와 reference라는 단어를 들어봐서 정리해 보기
둘 다 단어 뜻 그대로
함수에 정의한 매개변수의 형태가 인자의
Call by value 값이냐 아니면
Call by reference 주소를 전달하는 방식이냐의 차이다.
여기서 자바가 어떤 종류일까 말한다면 둘 다 인줄 알았는데 정확히는 Call by value 였다.
Call by value
함수 호출 시 넣는 변수의 값이 매개변수에 복사되어 전달된다. 매개변수에 데이터 변형이 일어나도 변수에는 영향이 없다.
method는 {를 만날 때 해당 함수의 지역변수와 매개변수를 저장하는 공간인 스택프레임이 생긴다. 스택프레임 : 지역변수, 매개변수, 연산의 중간 결과 등을 저장한다.
public class Main {
public static void main(String[] args) {
int a = 10;
sub(a);
System.out.printlnt(a);
}
public static void sub(int a) {
a++;
}
}
각각 실행 시 main과 sub 메소드에는 stack안에 메모리(스택프레임)가 할당된다.
- main메소드가 호출되면 메모리가 할당되고 지역변수 a값이 저장된다.
- 코드가 순차적으로 실행
- main에서 sub메소드를 실행한다. main메소드는 대기 상태
- sub메소드의 { 와 만나 sub메소드가 메모리에 할당되고 매개변수 a에 main메소드의 변수 a값이 복사되어 새로운 지역 변수에 저장.
- sub메소드의 코드에 의해 a값은 11된다.
- sub메소드의 } 수행이 완료되어 스택 프레임이 삭제된다.
- 호출한 main메소드로 되돌간다.
- 다음 코드를 진행한다.
- main메소드이 변수 a의 값을 출력한다.
- main의 } 와 만나 수행이 완료되고 호출 스택에서 사라지고 완전히 비워지므로 프로그램이 종료된다.
이때 출력된 값은 10으로 변함이 없다.
값을 넘겨준 메소드의 변수와 넘겨받은 메소드의 변수는 같은 값이지만 다른 공간이다. 따라서 아무리 바꿔도 영향을 줄 수 없다.
객체일 때도 이 경우가 동일하다.
call by reference의 경우는 매개변수의 참조변수에 새로운 객체를 넣었을 경우 호출한 메소드의 객체의 주소값도 바뀐다는경우다.
예를 들어
public class Main {
public static void main(String[] args) {
Ref ref = new Ref(100);
System.out.printlnt("before = " + ref.value);
sub(ref);
System.out.printlnt("after = " + ref.value);
}
public static void sub(Ref ref) {
ref = new Ref(101);
System.out.printlnt("inline = " + ref.value);
}
}
class Ref {
int value;
public Ref(String value) {
this.value = value;
}
}
일때 자바에서는
before = 100
inline = 101
after = 100
이 출력된다.
만약 call by reference면 sub의 ref에 바뀐 객체의 주소가 그대로 호출한 메소드의 변수에 적용되어 after의 값이 101이 되어야 한다.
즉 call by reference일 경우 변수의 주소값이 매개변수에 전달되는 것이지
객체의 주소값이 전달되는 것이 아니다.
이 경우를 생각하면 java가 call by value라는 것을 알 수 있다.