Call by Value

Class CallByValue{
		public static void swap(int x, int y) {
			int temp = x;
			x = y;
			y = temp;
}
public static void main(String[] args) {
			int a = 10;
			int b = 20;
			System.out.println("swap() 호출 전 : a = " + a + ", b = " + b);
			swap(a, b);
			System.out.println("swap() 호출 후 : a = " + a + ", b = " + b);
	}
}
swap() 호출 전 : a = 10, b = 20
swap() 호출 후 : a = 10, b = 20

위 코드에서 a,b가 swap되지 않은 이유는 매개변수 x,y와 인자 a,b가 서로 다르기 때문입니다.

Call by Value의 동작구조때문인데, 메서드 호출 시 매개변수에 인자의 메모리에 저장된 값이 복사되어 전달하기 때문입니다.

Call by reference

call by reference는 메서드 호출 시 인자가 값이 아닌 주소를 넘겨줌으로써 주소를 참조하여 데이터를 변경할 수 있습니다.

Class CallByReference{
    int value;
    CallByReference(int value){
	    this.value=value;
    }
public static void swap(CallByReference x,CallByReference y){
		    int temp=x.value;
		    x.value=y.value;
		    y.value=temp;
    }
public static void main(String[]args){
    CallByReference a=new CallByReference(10);
    CallByReference b=new CallByReference(20);
    System.out.println("swap() 호출 전 : a = "+a.value+", b = "+b.value);
    swap(a,b);
    System.out.println("swap() 호출 전 : a = "+a.value+", b = "+b.value);
		}
}
swap() 호출 전 : a = 10, b = 20
swap() 호출 후 : a = 20, b = 10

main()에서 선언된 CallByReference타입의 객체를 new로 생성하여, 이때 생성된 객체(인스턴스)는 힙영역에 저장되어, a,b인자는 해당 인스턴스의 메모리 주소를 참조합니다. 따라서 swap함수 역시 주소를 전달받아 주소안의 값을 변경하게 되므로, 스택영역과 상관없이 힙영역의 객체값이 변하게 됩니다.

class A{}

public class HeapArea {
	public static void main(String[] args) {
		A a = null; // A타입의 a객체 선언 및 Stack 영역 공간 할당
		System.out.println(a); // 결과 : null
		a = new A(); // Heap 메모리에 공간 할당 및 객체(a)에 참조값 할당
		System.out.println(a); // 결과 : @15db9742
	}
}

자바에서는 위 코드와 같이 참조형의 데이터 타입을 갖는 객체와 배열 등은 Heap영역에 데이터가 저장됩니다. 이때 변수는 Stack영역의 공간에서 실제 데이터가 저장된 Heap영역의 참조값(ref value, 메모리 참조를위한 해시값)을 new연산자를 통해 리턴받습니다.

즉, 실제 데이터를 갖고있는 Heap영역의 참조값을 Stack영역의 객체가 갖고있는것입니다.

JAVA 메모리 구조

Untitled