모르는 용어 정리

Pass by value vs Pass by reference

참깨빵위에참깨빵_ 2024. 10. 19. 01:40
728x90
반응형

참조 타입, 값 타입의 차이처럼 값에 의한 전달, 참조에 의한 전달도 존재한다. 둘의 차이는 무엇인지 확인한다.

예시코드는 마찬가지로 자바를 사용한다.

 

https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference

 

Java is Pass by Value, Not Pass by Reference | DigitalOcean

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

www.digitalocean.com

많은 자바 개발자는 자바가 값으로 전달되는지 참조로 전달되는지 궁금해한다. 먼저 값으로 전달과 참조로 전달은 뭘 의미하는가?

- 값으로 전달 : 함수 매개변수 값을 다른 변수에 복사한 다음 복사된 객체를 메서드에 전달한다. 이 때 메서드는 복사본을 사용한다
- 참조로 전달 : 실제 매개변수에 대한 별칭 or 참조가 메서드에 전달된다. 이 때 메서드는 실제 매개변수에 접근한다

변수가 객체에 대한 참조를 보유하더라도 해당 객체 참조는 메모리에서 객체의 위치를 나타내는 값이기 때문에 기술적으로 자바는 항상 값으로 전달된다. 따라서 객체 참조는 값으로 전달된다. 참조 자료형, 기본 자료형 모두 값으로 전달된다...(중략)

 

https://medium.com/javarevisited/is-java-pass-by-reference-or-pass-by-value-f03562367446

 

Is Java ‘pass-by-reference’ or ‘pass-by-value’?

The age-old question that sparks confusion and debate amongst Java developers is whether Java uses ‘pass-by-reference’ or ‘pass-by-value’…

medium.com

(중략)...자바는 pass by value 언어다. 자바가 객체, 객체의 참조를 처리하는 방식 때문에 혼동이 발생한다. 메서드에 객체를 전달할 때는 pass by reference처럼 실제 객체를 전달하는 게 아니라 객체의 참조값(메모리 주소)을 전달하는 것이다. 따라서 메서드 안에서 객체를 바꾸면 원래 객체에 영향을 준다...(중략)

 

결론은 자바는 Pass by value 형식으로 작동한다.

아래는 Pass by value와 Pass by reference를 확인하는 자바 예제 코드다.

 

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Main {
    public static void main(String[] args) {
        /* 기본형 데이터 : Pass by value */
        int num = 10;
        modifyPrimitive(num);
        System.out.println("After modifyPrimitive: " + num);

        /* 참조형 데이터 : Pass by value (reference는 value로 전달됨) */
        Person person = new Person("John");
        modifyObject(person);
        System.out.println("After modifyObject: " + person.getName());
    }

    public static void modifyPrimitive(int x) {
        x = 20;  // 이 함수 안에서만 x의 값이 변경된다
    }

    public static void modifyObject(Person p) {
        p.setName("Doe");  // 참조된 객체의 상태가 변경된다
    }
}

// After modifyPrimitive: 10
// After modifyObject: Doe

 

기본형 데이터 처리부터 확인한다. num 변수는 int 타입인 걸 볼 수 있다. 이 데이터를 함수로 전달할 때 값을 복사해서 전달하기 때문에 modifyPrimitive()를 호출하면 num에 담긴 10이 함수 매개변수인 x로 복사된다.

 

public static void modifyPrimitive(int x) {
    x = 20;  // 이 함수 안에서만 x의 값이 변경된다
}

 

함수 안에서 x의 값은 20으로 변경된다. 그러나 x는 num 값이 복사된 변수다. 즉 함수 안에서만 x는 20으로 바뀌고 함수가 종료되면 x는 사라진다. 함수 안에서 num을 조작하는 로직이 없기 때문인 것도 있다.

더 본질적인 이유는 자바의 함수 호출 방식 자체가 Pass by value기 때문이다. 자바는 모든 값을 복사해서 함수에 전달한다. 기본형 변수의 경우 그 값이 복사되기 때문에 함수 안에서 해당 복사본을 조작하고 원래 값에는 영향을 주지 않는다. x는 num의 복사본일 뿐이라 안에서 100을 넣건 100만을 넣건 num과 전혀 상관없는 새로운 값이 된다.

 

Person 객체의 상태를 바꾸는 부분을 확인한다.

 

Person person = new Person("John");
modifyObject(person);

 

person은 객체를 가리키는 참조값을 갖고 있다. 이 참조값은 메모리 상의 객체를 가리키고 있다. 이후 modifyObject()를 호출하면 참조값의 복사본이 함수에 전달된다. 즉 person 변수가 전달되는 게 아니라 person이 가리키는(=바라보는) 객체의 메모리 주소(=참조값)만 함수에 전달된다.

 

public static void modifyObject(Person p) {
    p.setName("Doe");  // 참조된 객체의 상태가 변경된다
}

 

위 함수의 p와 person은 모두 같은 객체를 가리킨다. 그리고 setter 함수가 객체의 상태를 Doe로 바꾸면, p와 person은 모두 같은 객체를 가리키기 때문에 함수 밖에 있는 person 변수의 상태에도 변화가 일어난다.

그러나 참조 변수 자체는 바꿀 수 없다. 무슨 말이냐면 아래처럼 수정할 경우를 본다.

 

public static void modifyObject(Person p) {
    p = new Person("Doe");
}

 

p 변수에 새 인스턴스를 할당한다. 이제 p는 Doe란 상태를 가진 새 객체를 가리키게 되는데 이 변경은 함수 안에 있는 p 변수에만 적용된다. 함수가 종료되면 수정된 p를 쓰는 곳은 코드에서 어디에도 없기 때문에 함수 밖에 있는 person 변수는 여전히 John이란 상태를 갖고 있다.

실제로 위와 같이 변경한 후 재실행하면 John이 출력된다. Doe는 출력되지 않는다.

 

위 예시를 정리하면

 

  • 객체의 상태는 함수 안에서 바꿀 수 있다
  • 참조변수 자체는 함수 안에서 바꾸더라도 함수 밖에는 영향을 주지 않는다 <- 자바는 참조값의 복사본을 전달하기 때문

 

기본형의 경우

 

  • 기본형 데이터를 함수에 전달할 땐 값 자체가 복사돼 함수로 전달된다
  • modifyPrimitive()가 끝나면 x는 사라지고 num 변수의 값은 10을 유지한다
  • 기본형 데이터를 함수로 전달할 때 함수 안에서의 변경은 원래 값에 영향을 주지 않는다 <- 자바는 값의 복사본을 전달하기 때문

 

참고로 코틀린에서도 동일하게 Pass by value 방식으로 참조변수의 복사본을 전달한다. 그래서 자바 코드와 같은 결과를 볼 수 있다.

반응형