Java Mid 03 - Immutable Object

불변 객체 (Immutable Object) - 도입

  • 앞에서 논의한 문제는 공유된 객체의 값이 변경됨으로 인해 발생했다.
  • 자바에서 참조형 변수는 하나의 객체를 공유할 수 있지만, 이 자체는 문제가 아니다. 문제의 직접적인 원인은 공유된 객체의 값이 변경되었기 때문이다.

문제 상황 예시

  • 초기에는 ab가 같은 "서울" 주소를 사용해야 한다. 이후 b의 주소를 "부산"으로 변경해야 한다.
java코드 복사
Address a = new Address("서울");
Address b = a;

  • b = a처럼 동일한 "서울" 주소 인스턴스를 ab가 함께 사용하는 것이 메모리와 성능 면에서 더 효율적이다.
  • 인스턴스를 하나만 생성하므로 메모리가 절약되고 생성 시간이 줄어들어 성능이 향상된다.

이처럼 Address b = a와 같이 공유 참조를 사용하는 것이 오히려 더 효율적입니다. 진짜 문제는 이후에 b가 공유 참조하는 인스턴스의 값을 변경하기 때문에 발생한다.

b.setValue("부산"); // b의 값을 부산으로 변경
System.out.println("a = " + a); // 사이드 이펙트 발생
System.out.println("b = " + b);

불변 객체의 이점

불변 객체는 생성된 후 내부 상태가 변하지 않는 객체를 말한다.

  • 안전한 공유: 불변 객체는 여러 쓰레드에서 안전하게 공유될 수 있다.
  • 내부 상태가 변경되지 않기 때문에 동기화가 필요 없다.
  • 사이드 이펙트 방지: 불변 객체는 내부 상태가 변경되지 않기 때문에 예상치 못한 변경으로 인한 사이드 이펙트를 방지할 수 있다.

불변 객체의 구현

Address 클래스를 불변 객체로 만들기

  • 모든 필드를 final로 선언한다.
  • 필드는 생성자를 통해 초기화한다.
  • 값을 변경할 수 있는 메서드를 제거한다. setValue() 같은

예시코드

java코드 복사
public final class Address {
    private final String value;

    public Address(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}
  • 이제 Address 객체는 불변이므로, 내부 상태가 변경되지 않는다. 따라서 ab가 같은 인스턴스를 공유하더라도 안전하게 사용할 수 있다.

예시코드


Address a = new Address("서울");
Address b = a;

System.out.println("a = " + a.getValue()); // 출력: 서울
System.out.println("b = " + b.getValue()); // 출력: 서울

// 새로운 객체를 생성하여 변경된 값을 반영
b = new Address("부산");

System.out.println("a = " + a.getValue()); // 출력: 서울
System.out.println("b = " + b.getValue()); // 출력: 부산

  • 이제 b"부산"으로 변경할 때 새로운 Address 객체를 생성하므로, 기존 a와 공유된 인스턴스는 변경되지 않는다. 따라서 사이드 이펙트가 발생하지 않는다.

그래도 불변객체에서 값을 변경해야 한다면?

  • 값을 변경해야 하는 메서드를 구현해야 한다고 하면 이미 불변객체라는 개념에서 벗어난다.
  • 그래도 변경해야 한다면 ?
public class ImmutableObj {

     private final int value;
     
     public ImmutableObj(int value) {
         this.value = value;
         
}    //값은 변경하되 새로운 인스턴스(객체)를 반환한다.
     //변경된 데이터는 새로운 객체에 담아서 반환.
     public ImmutableObj add(int addValue) {
         int result = value + addValue;
         return new ImmutableObj(result);
}

새로운 인스턴스에 값을 담으면 된다.

Reference

인프런 김영한님의 실전 자바 강좌



© 2022. by taewoo

Powered by taewoo