본문 바로가기

공부함/JAVA

[ java ] call by value 와 call by reference

call by value ( 값에 의한 호출 ) 

- 인자(parameter)로 받은 값을 복사하여 처리한다.

- 복사되게 때문에 메모리 량이 늘어난다. 과부하의 원인이 된다. 

- 복사하여 사용하기 떄문에 원래의 값에는 영향을 미치지 않는다.

 

- 함수가 호출될 때 메모리 공간 안에 함수를 위한 별도의 임시공간이 생성된다.

함수가 종료되면 해당 공간은 함수가 종료되면 사라진다  

- 스택 프레임 : 함수 호출 시 할당되는 메모리 블록 ( 지역변수의 선언으로 인해 할당되는 메모리 블록 ) 

- call by value : 값에 의한 호출방식은 함수 호출할 때 전달되는 변수의 값을 복사하여 함수의 파라미터로 전달한다.

복사된 파라미터는 함수 안에서 지역적으로 사용되는 지역변수의 특성을 가진다.

함수안에서 파라미터의 값이 변경되어도, 외부에 있는 변수의 값은 변경되지 않는다.

- java의 경우 함수에 전달되지 않는 파라미터의 데이터 타입에 따라서 함수 호출방식이 달라진다. 

( 원시자료형 : call by value 로 동작  ( int, short, long, float, double, char, boolean ) 

- 기본형

 

call by reference ( 참조에 의한 호출 ) 

- 인자(parameter)로 받은 값을을 참조하여 직접 값에 영향을 준다. 

- 직접 참조하기 떄문에 처리가 빠르다. 

- 직접 참조를 하기 떄문에 원래의 값에 영향을 받는다. 

( 참조 자료형 : call by reference 로 동작한다 ( array, class instance )

- 함수가 호출될 떄 메모리 공간안에 함수를 위한 별도의 임시공간이 생성된다.

- 참조에 의한 호출방식은 함수 호출 시 파라미터로 전달되는 변수의 레퍼런스를 전달한다. ( 해당 변수를 가르킨다 )

- 함수 안에서 파라미터의 값이 변경되면 argument로 전달된 객체의 값도 함꼐 변경된다. (전역변수처럼)

- 객체형 , 해당 객체의 주소값을 직접 넘기는 것이 아닌, 객체를 보는 또 다른 주소값을 만들어서 넘긴다.

reference를 직접 변경하는 것이 아닌 reference가 참조하는 객체의 값을 변경한다.  ( reference.value )

 

 

예제 1) call by value

아래의  swap는 a=1, b=2로 나타난다.

함수를 호출하고 내용을 교체했지만 함수에서는 호출된 파라미터를 사용하고 별도로 저장하지 않는다.

그래서 주석으로 적힌 결과가 출력된다.  ( 즉, swap 되지 않는다.) 

public class SwapTest {
    public static void swap(int a, int b) {
        int tmp = a;
        a = b;
        b = tmp;
    }
 
    public static void main(String[] args) {
        int a = 1;
        int b = 2;
 
        System.out.println("a = " + a + ", b = " + b); // a = 1, b = 2
        swap(a, b);
        System.out.println("a = " + a + ", b = " + b); // a = 1, b = 2
    }
}

 

예제 2) call by reference

새로운 객체를 만들어 함수로 넘기면 return을 하지 않아도 변경된 값이 객체에 저장된다.

public class SwapTest {
    int value;
    
    public SwapTest(int value) {
        this.value = value;
    }
    public static void swap(SwapTest a, SwapTest b) {
        int temp = a.value;
        a.value = b.value;
        b.value = temp;
    }
 
    public static void main(String[] args) {
        SwapTest a = new SwapTest(1);
        SwapTest b = new SwapTest(2);
        System.out.println(a.value + " " + b.value);
        swap(a, b);
        System.out.println(a.value + " " + b.value);
    }
}

 

 

 

aList를 가져와서 targetModel안의 일부 값을 변경해야하는 작업을 진행하게 되었다. 

그래서 개발결과물 중 아래의 소스코드처럼 가져온 대상 리스트를 유지하며 새 리스트를 만들었다.

List<targetModel> aList = listDAO.getTargetList(); 
List<targetModel> bList = new List<targetModel>;

for ( targetModel item : aList ){
	//item의 name를 가져와 item의 NewName에 [oldname]를 추가
	String NewName = "[" + item.getName + "]" ;  
	item.setNewName(NewName); 
    bList.add(item);
}

 

이 부분을 검토해 주신 사수로부터 "call by value와 call by reference에 대해 공부해보고 다시 처리해주세요"라고 권유받아 공부하게 되었다.

 call by value 와 call by reference에 대해 공부해보니 파라미터로 할당되는 aList에서 꺼낸 targetModel의 값을 변경하면 어디에서 호출 되더라도 변경된 값이 바로 모델에 저장된다. 원하는 결과값이 aList에 저장되기 때문에 굳이 새 리스트인 bList에 저장할 필요가 없다.

그래서 bList를 제거함으로 현상을 해결하였다. 

List<targetModel> aList = listDAO.getTargetList(); 

for ( targetModel item : aList ){
	//item의 name를 가져와 item의 NewName에 [oldname]를 추가
	String NewName = "[" + item.getName + "]" ;  
	item.setNewName(NewName); 
}

 

 

 

 

출처, 참고 

https://codingplus.tistory.com/29

https://devlog-wjdrbs96.tistory.com/44