BackEnd/Java

JAVA에 Call by refernce는 없다.

Potwings 2023. 7. 3. 20:54

메소드 호출 시 파라미터의 값을 불러오는데는 Call by Reference와 Call By Value 두가지 방법이 있다.

 

Call by Reference와 Call By Value란?

Call By Reference (참조에 의한 호출)

메소드 호출 시 파라미터로 변수를 직접 전달한다. 메소드 내부에서 파라미터에 대한 수정이 발생할 경우 원본에도 동일하게 적용된다. 자바에서는 이 방식으로 동작하지 않는다.

Call By Reference의 경우 두개의 변수는 동일한 변수이다.

Call By Value (값에 의한 호출)

메소드 호출 시 파라미터로 변수의 값을 복사하여 전달한다. 메소드 내부에서 파라미터에 대한 수정이 발생할 경우 원본에는 반영되지 않는다.

Call By Reference의 경우 두개의 변수는 다른 변수이다.

 

자바에서의 파라미터 전달 방식은 Call By Value이다.

자바는 파라미터 전달 시 Call By Value 방식으로만 동작한다.

 

Call By Reference라고 착각하게 되는 이유

Java에서 Call By Reference라고 착각하게 되는 경우가 있다.(내가 그랬다)

필자는 과거에 객체를 파라미터로 전달받아 set을 하면 해당 객체의 값이 변경되기 때문에 Call by Reference라고 오해했었다.

메소드 내부에서 set했더니 토핑이 바뀌네...? Call By Reference 인가..?

절대 아니다 자바는 Call By Value이다.

 

자바의 파라미터 전달하는 방식에 대해 알아보면 쉽게 이해할 수 있다.

 

자바에서 생성하는 변수의 타입은 원시 타입(Primitive Type)참조 타입(Reference Type)이 있다.

타입에 따라 파라미터로 전달하는 방법이 다르므로 우선 둘의 변수 선언 시 데이터 저장 위치부터 알아보자

 

자바 변수 선언 시 데이터 저장 위치

원시 타입의 경우 Stack 영역에 변수와 값을 모두 저장한다.

하지만 참조 타입의 경우 변수는 Stack 영역에 객체의 주소값을 저장하나 데이터값은 Heap 영역에 저장한다.

자바의 변수 데이터 저장 위치

참조타입을 파라미터로 전달할 경우

참조 타입의 경우 변수의 데이터 값을 복사하는 것이 아니라 변수에 담고 있는 주소값을 복사한다.

따라서 변수가 가르키고 있는 Heap영역에 존재하는 데이터값은 동일하다.

주소값이 동일하다.

이로 인하여 메소드 내부에서 setter를 통하여 값을 변경하더라도 실제 데이터의 주소값은 동일하기 때문에 기존 객체도 변경이 되는 것이다.

 

메모리 내부에서의 동작을 보면 아래와 같다.

둘다 동일한 데이터값을 바라본다.

파라미터로 전달 시 새로운 변수에 stack에 존재하는 데이터 주소값을 복사하여 준다.

이로 인해 참조타입을 파라미터로 전달받아 set 할 경우 기존 데이터에도 변경 사항이 반영되는 것이다.

 

만일 아래와 같이 파라미터에 새로운 값을 할당한 후 변경할 경우 기존 데이터에는 반영되지 않는다.

새로운 피자를 만들어 주소값이 달라진 모습, 마찬가지로 토핑도 바뀌지 않는다.

 

원시타입을 파라미터로 전달할 경우

아래와 같은 메소드를 통하여 원시타입을 파라미터로 전달할 경우를 알아보자.

실행결과

changeInt() 메소드에서 변경한 변수의 값은 파라미터로 num을 복사하여 만든 paramNum의 값을 변경한 것이다.

 

메모리 내부에서의 동작을 보면 이렇게 진행된다.

원시타입 파라미터 전달 시 메모리 내부에서의 동작

 

 

 

참고자료 : https://bcp0109.tistory.com/360