자바의 primitive 타입은 call by value , wrapper class 는 call by reference 라고 생각 하고 있었다.
정말 그런지 테스트하고 검증하여 알아보자.😅
우선 결과부터 말하면 자바는 모든경우에서 call by value 이다.
테스트를 통해서 알아보자.
다음 코든는 테스트에 사용될 name 필드를가지는 Dog 클래스이다.
@Getter
@Setter
@AllArgsConstructor
public class Dog {
public String name;
}
위의 Dog 클래스를 이용하여 call by reference, value 인지 확인하는 테스트를 진행 하였다.
@Slf4j
class DogTest {
@Test
@DisplayName("Call by Reference 일경우 원본 변화가 생긴다.")
void call_by_test(){
//given
//when
Dog dog=new Dog("foo");
log.info("start name is .. :"+dog.getName());// foo
foo(dog);
log.info("end name is .. :"+dog.getName()); // foo -> expected asdf actual : foo
log.info("set new dog .. :"+dog.getName()); // foo
//then
}
public void foo(Dog dog){
Dog tmp=new Dog("asdf");
dog=tmp; // call by reference 일 경우 dog 메모리를 tmp에 대입한다. (원본에 영향을 준다.)
dog.setName("var");
log.info("changed name is.. :"+dog.getName());
}
foo 메서드 가 끝나더 라도 foo 에서 dog = tmp 를 대입하더라도 call_by test에 돌아왔을때 원본의 변화가 없을 것이다.
foo 메서드가 call by reference로 동작한다면
foo 메서드 실행시 dog라는 참조에 tmp를 대입 하므로 foo 메서드가 끝나더라도
foo 메서드를 호출한 call_by_test 에서도 dog 내용의 변화에 영향이 있을것이다.
foo 에서는 tmp로 새로운 Dog 객체를 생성 한 후 파라미터 dog 에 대입했다.
call by reference 일 경우 원본에 변화가 있을 것 이다.
1. foo 메서드가 실행되면서 foo 에서 foo의 주소값을 '복사' 한 dog 변수를 가진다. 이때 call by test의 dog 와 foo 의 dog 는 같은 객체를 가르킨다.
tmp 라는 새로운 Dog 객체를 만들고 dog 에 대입하면 위와 같이 동작한다.
foo 가 실행이 끝나면 tmp 는 더이상 가르키는 멤버 변수가 없으므로 GC에 의해서 지워진다.
call by test 의 dog 객체는 변하지 않는다.
완전히 이해해 버렸네요 :)