1 분 소요

자료 구조를 배우면서 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안에 메모리(스택프레임)가 할당된다.

  1. main메소드가 호출되면 메모리가 할당되고 지역변수 a값이 저장된다.
  2. 코드가 순차적으로 실행
  3. main에서 sub메소드를 실행한다. main메소드는 대기 상태
  4. sub메소드의 { 와 만나 sub메소드가 메모리에 할당되고 매개변수 a에 main메소드의 변수 a값이 복사되어 새로운 지역 변수에 저장.
  5. sub메소드의 코드에 의해 a값은 11된다.
  6. sub메소드의 } 수행이 완료되어 스택 프레임이 삭제된다.
  7. 호출한 main메소드로 되돌간다.
  8. 다음 코드를 진행한다.
  9. main메소드이 변수 a의 값을 출력한다.
  10. 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라는 것을 알 수 있다.