[ 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);
}
출처, 참고