카테고리 없음

Java에서 int를 매개변수로 넘길 때 값이 갱신되지 않는 이유

nagrang 2025. 3. 7. 16:24

코테를 풀다가 재귀 호출할 때 값이 갱신되지 않았다.

문제의 코드는 아래인데, 최종 갱신되는 `result` 값을 함수의 반환값으로 넘기고 싶었다. 근데 값이 분명 10으로 바뀌었는데 이전 콜스택으로 넘어가니 다시 기존 값이 되었다.

private void nCr(int depth, int N, int R, boolean[] v,  int result,  int [][] friends){
    if(depth == R){
        // 계산
        // 이때 갱신이 안되나? 안됨. 왜 안돼?
        result = Math.min(result, diff(v, friends));
        // min 값 갱신
        return;
    }

    for(int i = depth; i<N; i++){
        v[i] = true;
        nCr(depth+1, N, R, v, result, friends);
        v[i] = false;
    }
}

 

우선 래퍼런스 객체가 아니여서 그런가? 했다.

int와 long 처럼 자바의 기존 타입은 값에 의한 호출(pass by value)로 값만 복사되어 넘어간다고 한다. 그래서 값이 변경될 수가 없다.

 

그래서 래퍼런스 타입으로 알고있는 `Integer` 객체를 사용했다. 하지만 마찬가지로 값이 갱신이 안됐다. 이유를 찾아보니 Integer, String 와 같은 `래퍼 클래스`는 불변객체라고 한다. 불변객체란 한 번 생성된 값이 변하지 않는다는 특성을 가진다. 그럼 아예 변하지 않는 것일까? 

 

확인해보니,  아래 대입 연산을 할 때 새로운 Integer 객체가 생성된다.

result = Math.min(result, diff(v, friends));

 

래퍼런스 변수 답게 하나의 객체를 계속 사용할 줄 알았는데, 매번 새롭게 생성되서 혼동이 왔다.

 

그 이유는 `Integer`는 참조 타입(Reference Type)이긴 하지만, 불변 객체이기 때문이다. 즉 값이 변경되어도 내부적으로 새로운 Integer 객체가 생성될 뿐, 원래 객체가 변경되지 않는다.

 

또한 대입 연산자(`=`)는 참조(주소)를 변경하는 역할을 한다. 기존 result에 새로운 객체를 넣는 것이 아니라, 새로운 객체를 가리키도록 하는 것이다. 때문에 이때 `result`는 새로운 Integer 객체를 가리키게 되어서 기존의 객체와 연결이 끊어지게 된다. 그러니 갱신이 될리가 없다.

 

그러면 갱신을 해줄려면?

가변객체이면서 레퍼런스 변수를 이용하면 된다. 흔히 알고있는 배열(`[]`)을 사용하면 되는 것이다. 왜냐? 배열은 래퍼런스(주소 가리킴) 변수면서 내부의 값을 변경할 수 있는 가변 객체이기 떄문이다.

private void nCr(int depth, int N, int R, boolean[] v,  int [] result,  int [][] friends){
    if(depth == R){
        // 계산
        result[0] = Math.min(result[0], diff(v, friends));
        // min 값 갱신
        return;
    }

    for(int i = depth; i<N; i++){
        v[i] = true;
        nCr(depth+1, N, R, v, result, friends);
        v[i] = false;
    }
}

 

이러면 이전 콜스택으로 되돌아 와도 갱신된 값이 저장된다!