객체지향의 4대 특성(4) : 캡슐화 (2)

3. 참조 변수의 복사

기본 자료형 변수를 복사하는 경우 Call By Value(값에 의한 호출)에 의해 그 값이 복사되어 두 개의 변수는 서로에게 영향을 주지 않는다.

package reference;

public class CallByValue {
    public static void main(String[] args) {
        int a = 10;
        int b = a;
        
        b = 20;
        
        System.out.println(a);  // 10;
        System.out.println(b);  // 20;
    }
}

위의 예제를 보면 변수 a에 10을 대입한 후, 변수 b에 변수 a가 가진 값을 복사하고, 다시 변수 b에 20을 할당한 것을 볼 수 있다. 이때 a가 가진 값이 단순히 b에 복사된 것이고 a와 b 변수는 아무런 관계가 없는 것을 알 수 있다.

그렇다면 기본 자료형이 아닌 객체를 저장하고 있는 객체 참조 변수를 복사하는 경우는 어떨까? 이 경우를 Call By Reference(참조에 의한 호출) 또는 Call By Address(주소에 의한 호출)이라고 한다.

아래 예제 코드를 보자.

package reference;

public class CallByReference {
    public class void main(String[] args) {
        Animal ref_a = new Animal();
        Animal ref_b = a;
        
        ref_a.age = 10;
        ref_b.age = 20;
        
        System.out.println(ref_a.age) // 20
        System.out.println(ref_b.age) // 20       
    }
}

Class Animal{
    public int age;
}

뭔가 큰 차이가 느껴질 수도 있겠지만 사실은 Call By Value와 Call By Reference는 본질적으로 차이가 없다. 다만 차이라면 기본 자료형 변수는 저장하고 있는 값을 그 값 자체로 해석하는 반면, 객체 참조 변수는 저장하고 있는 값을 주소 또는 포인터로 해석한다는 차이가 있을 뿐이다.

만약 Animal 객체의 주소가 100번지라고 가정하면 위의 그림은 다음 그림과 같아진다.

주소를 보여주지는 않지만 참조하고 있는 객체에 대한 고유값을 보여주는 다음 코드를 실행해보면 ref_a와 ref_b는 결국 같은 값을 가지고 있음을 알 수 있다.

package reference;

public class CallByReference2 {
    public static void main(String[] args) {
        Animal ref_a = new Animal();
        Animal ref_b = a;
        
        System.out.println(ref_a); // reference.Aminal@15db9742 - 실행할 때마다 다르다.
        System.out.println(ref_b); // 바로 위와 같은 값이 출력된다.
    }
}

ref_a와 ref_b는 완전히 다른 변수다. 다만 같은 값을 가지고 있고 컴퓨터는 그 값을 주소로서 활용한다. 결국 두 변수가 같은 객체를 참조하고 있을 뿐이다. 참조하고 있는 객체가 같으니 참조하고 있는 객체의 변화에 함께 영향을 받을 뿐이다.

결국 Call By Reference와 Call By Value를 다르다고 이해하기보다는 기본 자료형 변수는 저장하고 있는 값을 그 값 자체로 판단하고, 참조 변수는 저장하고 있는 값을 주소로 판단한다고 이해하는 것이 더 쉽다.

참고

  • 스프링 입문을 위한 자바 객체지향의 원리와 이해

좋은 웹페이지 즐겨찾기