본문 바로가기

Language/Java

Call by reference 와 Call by Value 차이

반응형

Call by reference와 Call by value 의 차이에 대한 공부를 진행하던중

public class Test { 
	public static void change(String src){ 
    	src = "new"; 
    } 
    
    public static void main(String[] args) { 
    	String step = "old"; 
        System.out.println(step); 
        change(step); 
        System.out.println(step); 
    } 
}

"String 도 Reference type 이니까 Call by reference처럼 작동할거야!" 라는 물음에 위의 소스코드를 작성했다.

old 
old

결과값은 내가 생각했던 것과 전혀 다른 결과가 나왔다.

"왜 Reference type인데 결과 값이 new가 되지 않는거야?"

이 물음으로 시작해서 Call by reference와 Call by value에 대한 정리가 급히 필요 했다. 또한 자바는 Call by Value인지 Call by reference인지에 대해 결론을 내보려고 합니다.

아 먼저 Call by value 를 이야 기하기 전에 JVM의 메모리 영역에 대한 이해가 필요 합니다 .

0. JVM 메모리 구조란?

이번 글은 "Call by value 와 Call by reference 의 차이" 에 대한 내용을 정리하려고 하기 때문에 JVM의 구조중에 메모리 영역인 "Runtime Data Area"에 대해서만 정리 해보겠습니다.

Runtime Data Area는 JVM의 메모리 영역으로 자바 에플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역입니다

 

JVM 메모리구조

여기서 두가지를 볼건데 Stack 영역과 Heap영역에 대해 정리하겠습니다.

- Stack Area
메서드 안에서 사용되는 값들을 저장하고, 호출되는 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장합니다.

- Heap Area
인스턴스와 배열이 동적으로 생성되는 공간이고 Garbage Collection의 대상이 되는 영역이다
원천타입을 제외한 모든 데이터는 힙에 저장됩니다


1. Call by Value란?

Call by Value는 한마디로 '값에 의한 호출'을 의미한다.
난 이게 뭔말인지 이렇게 말하면 모르겠다. 예를 들어 보자

public class CallbyValue { 
	public static void run(int x, int y) { 
    	x = 30; y = 40; 
    } 
    
    public static void main(String [] args) { 
    	int a = 10, b = 20; 
        System.out.println("a = " + a + ", b = " +b); 
        
        run(a,b); 
        System.out.println("a = " + a + ", b = " +b); 
    } 
}

위 코드 결과는 아래와 같다.

a = 10, b = 20 
a = 10, b = 20

값이 바뀌지 않는다 .

a와 b를 파라미터로 전달하지만 run 메서드 내에 두 파라미터 값 x, y는 각각 a, b의 두 '값'만을
복사하여 x, y에 저장한다.
a 와 b의 값을 직접적으로 바꾸지 못하고 새로운 변수 x, y를 새로 만드는 셈이다.

결론적으로 Call by Value의 '값에 의한 호출' 의미는 파라미터로 전달받은 변수의 값을 받고 그 값을 복사해 새로 변수를 만들어 저장한다는 의미이다.

2. Call by reference

Call by reference는 한마디로 '참조에 의한 호출'이다 .
이말만 들으면 이것도 뭔말인지 모르겠다.

public class CallbyReference { 
	int num; 
   	public static void change(Test test) { 
    	test.value = 10; 
	} 
    
    public static void main(String [] args ) { 
    	Test test = new Test(); 
		System.out.println("test's value : "+test.value); 
        
        change(test); 
        System.out.println("test's value : "+test.value); 
	} 
}
test's value : 0 
test's value : 10

아까 Call by Value와 비슷한 예제 같은데 얘는 값이 바껴 있다??

사실 Java는 Call by Value로 작동한다. Call by Reference처럼 작동하는것 처럼 보이는 것 뿐이다.

그림을 통해 설명하자면

Call by Reference는 참조하는 변수가 '참조되는 변수의 주소값' 을 갖고 그 변수의 주소값으로 해당 값을 찾는 방식을
Call by Reference라고 부른다.

그럼 본래 자바는 Call by Reference 작동한다고 했는데 위의 코드 결과는 어떻게 된걸까?


자바에서는 똑같은 값이 있을 경우 메모리의 낭비를 줄이기 위해 그 값을 '가리키는' 형태로 메모리를 사용한다.
왜냐하면 자바는 C 처럼 메모리 자체에 접근할 수 없기 때문이다.
이 형태를 자바에서 일부의 사람들은 Call by Pointer라고도 합니다

결론적으로 말하자면 자바는 Call by Value 로 작동한다.
클래스, 배열은 Call by Reference처럼 작동하는걸로 보여질 뿐이다.
나머지 Primitive type과 String type의 변수들은 모두 Call by Value 로 작동한다 .

반응형