Java의 call by value

YeJi Kim·2023년 3월 13일
3

JAVA

목록 보기
5/5

자바는 call by value만 있다고 한다.
그렇다면 call by value란 무엇일까?
먼저 call by value와 call by reference에 대해 알아보자.🤗



Call by value

  • call by value = 에 의한 호출
  • 데이터 값을 복사해서 함수로 전달하기 때문에 호출자 변수와 수신자 파라미터는 Stack 영역 내에서 각각 존재하는 다른 변수이다.
  • 서로 다른 변수이기 때문에 원본의 데이터가 변경될 가능성이 없다.

Call by reference

  • call by reference = 참조에 의한 호출
  • 참조(=reference,주소)를 직접 전달하기 때문에 호출자의 변수와 수신자의 파라미터는 완전히 동일한 변수이다.
  • 메모리 공간 할당 문제는 해결했지만, 원본 값이 변경 될 수 있다는 위험이 존재한다.



reference type의 경우, Call by reference처럼 보인다❓🤔

메서드를 통해 매개변수로 객체를 전달하고 객체의 속성을 변경할 수 있다.
자바는 call by value이기 때문에 원본 데이터가 변경될 가능성이 없다고 했는데 어떻게 된 것일까?! 😮

다음 코드를 통해 진실을 알아보자.

public class Call_by_reference {
    public static void main(String[] args) {
        Human h = new Human("토비", 40);
        System.out.println("1. " + h);
        modifyAge(h);	// 객체의 age 속성값을 변경하는 메서드 호출 
        System.out.println("2. " + h);
        modify(h);		// 새로운 객체를 참조하는 메서드 호출 
        System.out.println("3. " + h);
    }

    public static void modify(Human a) {
        a = new Human("hi", 2);
        System.out.println("새로운 객체의 hashCode : " + a.hashCode());
    }

    public static void modifyAge(Human a) {
        a.age += 2;
        System.out.println("age 속성 변경 후 : " + a.hashCode());
    }
}

class Human {
    public String name;
    public int age;

    Human(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return this.name + ", " + this.age + ", " + this.hashCode();
    }
}

출력결과:
1. 토비, 40, 622488023
age 속성 변경 후 : 622488023
2. 토비, 42, 622488023
새로운 객체의 hashCode : 1550089733
3. 토비, 42, 622488023

위의 코드에서 age 속성 값을 변경하는 modifyAge 메서드의 매개변수로 h 객체를 전달했을 때 age값이 변경되었다. 이를 통해, modifyAge 메서드의 매개변수 a가 원본 변수인 h와 같은 주소를 가리키고 있다는 점을 확인할 수 있다.

새로운 객체를 할당해주는 modify 메서드의 매개변수로 h 객체를 전달했을 때 메서드가 완료되고 난 다음에도 h 객체는 같은 hashCode 값을 갖고 있다. 하지만 출력문을 통해 메서드에서 새로운 객체를 할당했을 때 매개변수의 hashCode 값이 1550089733으로 변경되었던 점을 확인할 수 있다. 이는 자바가 Call by value 방식으로 동작하기 때문이다. reference type의 변수인 h의 값(주소값)을 복사해서 메서드로 전달했다. 이 때문에 매개변수 a의 값은 새로운 객체의 주소값으로 변경되었지만 원본 변수인 h의 값은 변경되지 않았다.

따라서 reference type일 경우에도 자바가 call by value 방식으로 동작하는 것을 확인할 수 있다.
Call by Reference는 참조 자체를 넘기기 때문에 새로운 객체를 할당하면 원본 변수도 영향을 받는다.


위의 코드의 동작 과정을 그림으로 정리해보자.






토비의 스프링 저자(이일민님)의 견해



나의 결론

내가 이해한 바는 다음과 같다. (틀릴 수도 있다. 댓글로 알려주세요...)

자바는 call by value만 사용한다.

reference type 변수를 메서드의 매개변수로 넘겨주는 경우, call by reference value인 주소값을 복사해서 매개변수에 넘겨준다.

=> reference value인 주소값을 넘겨주는 경우, 메서드의 매개변수가 원본 변수와 같은 주소값을 가리키고 있기 때문에 call by value 방식임에도 불구하고 원본 변수의 속성이 변경될 수 있다. 하지만 원본 변수의 값(=객체의 주소값)을 복사해서 전달한 덕분에, 매개변수에게 새로운 객체를 할당하더라도 원본 변수의 값(=객체 주소값)이 변경되지 않는다.
따라서, 자바는 call by reference를 사용하지 않는다.

profile
이전의 기록들 👉 https://blog.naver.com/reviewerkyj

6개의 댓글

comment-user-thumbnail
2023년 3월 13일

다소 헤깔릴 수 있는 내용들이었는데, 감사합니다!

1개의 답글
comment-user-thumbnail
2023년 3월 20일

자바에서 by reference라는 말이 나온다는 점이 헷갈렸는데, by reference value 라고 딱 집어주셔서 이해가 잘 됐습니다. 제 생각과 예지님의 결론이 맞는 것 같네용!

1개의 답글
comment-user-thumbnail
2023년 3월 23일

와 이런 개념이었군요 토비님 설명과 마지막 요약까지!! 너무 알차고 유용하네요 잘 배우고갑니다 감사합니다^^

1개의 답글