자바의 arguments 참조방식

Rowan Lee·2024년 12월 25일

자바

목록 보기
7/10

프로그래밍 언어의 함수나 메서드는 function call stack에 담겨 언어 고유의 방식에 의해 arguments들을 사용한다. 이때 메서드 호출의 깊이가 깊어진다면 call by value, call by reference인지를 충분히 고려해야 메모리를 안전하게 관리할 수 있다. 따라서 자바가 어떻게 arguments들을 처리하는지 정리했다.

자바의 arguments

결론 : 참조방법은 primitive type / reference type에 따라 결정된다.
자바에는 몇가지 원시 자료형이 존재한다. 만약 원시 자료형이라면 call by value, 참조 자료형이라면 call by reference로 동작한다.

단. 재할당은 immutable reference type / mutable reference type을 고려해야 한다.
Integer과 같은 Wrapper class도 reference type이다. 그렇다면 아래와 같이 값을 재할당한다면 어떨까?

private static void f(Integer a) {
	a = 1;
}
public static void main(String[] args) {
	Integer a = 0;
    f(a);
    // a = ?
}

답은 0이다. main에서 선언한 a의 주소가 call by reference로 호출되는 것은 맞다. 그렇다면 반환값이 없어도 1로 변해야하는거 아닌가 생각하기 쉽다.
핵심은 Wrapper class는 immutable하다는 점이다. 즉 값이 변경되면 완전히 새로운 주소를 사용한다. 따라서 기존의 주소와 상관이 없어지기에 a의 값은 마치 call by value와 비슷하게 main의 a에는 변화를 주지 못한다.

private static void f(Integer a) {
	a = 1; // 해당 시점에 콜 스택의 a는 완전히 다른 객체의 주소가 들어간다.
}
public static void main(String[] args) {
	Integer a = 0;
    f(a);
}

// 즉 아래코드와 비슷하게 동작한다.
    private static void test(MyInt c) {
        c = new MyInt();
        c.x = 0;
    }

    public static void main(String[] args) {
        MyInt c = new MyInt(); // 참조타입
        c.x = 3;
        test(c);
        System.out.println(c); // 3
    }

정리해보자면 immutable reference type의 경우 함수 호출시에는 call by reference로 넘어가지만 재할당되면 관련없는 다른 주소를 받게 된다.
mutable reference type의 경우 재할당이 이루어지면 마찬가지로 다른 주소를 받지만, 필드의 변경만 일어나면 그 변경이 그대로 객체에 전달된다.

검증

arguments들의 참조관계를 한눈에 파악하고자 밑의 코드로도 검증해보았다.

public class Main {
    static class MyInt {
        int x;
    }

    private static void test(int a, Integer b, MyInt c) {
        a = 0;
        b = 0;
        c.x = 0;
    }

    public static void main(String[] args) {
        int a = 1; // 원시타입
        Integer b = 2; // 참조타입 & immutable
        MyInt c = new MyInt(); // 참조타입
        c.x = 3;

        test(a, b, c);
        System.out.println("a = " + a + "; b = " + b + "; c = " + c.x);
    }
}

// 결과 : a = 1; b = 2; c = 0 즉 c만 변경되었다.
profile
CS/Software Engineer

0개의 댓글