포스트

불변 객체

불변 객체

기본형과 참조형의 공유

  • 기본형: 하나의 값을 여러 변수에서 절대로 공유하지 않음
  • 참조형: 하나의 객체를 참조값을 통해 여러 변수에서 공유 할 수 있음

공유 참조와 사이드이펙트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Address {

  private String value;

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

  public String getValue() {
    return value;
  }

  public void setValue(String value) {
    this.value = value;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class RefMain1_1 {

  public static void main(String[] args) {
    //참조형 변수는 하나의 인스턴스를 공유할 수 있다.
    Address a = new Address("서울");
    Address b = a;
    System.out.println("a = " + a);
    System.out.println("b = " + b);

    b.setValue("부산"); //b의 값을 부산으로 변경해야함
    System.out.println("부산 -> b");
    System.out.println("a = " + a); // 부산
    System.out.println("b = " + b); // 부산
  }
}

b만 변경하고 싶었는데 a,b 모두 변경되어 사이드 이펙트가 발생하였습니다.

각각 new Address() 하여 a,b에 넣어줄 수 있지만, 여전히 누군가 변경한다면 사이드 이펙트의 위험이 있습니다.

공유 참조를 막을 방법은 없으니 객체 자체를 불변으로 만들어 사이드이펙트를 방지할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
public class ImmutableAddress {

  private final String value;

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

  public String getValue() {
    return value;
  }
}

불변 객체도 값을 변경하고 싶을 때

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
  }

  public int getValue() {
    return value;
  }
}

이처럼 새로운 불변 객체를 생성하여 반환하도록 하여 값을 수정할 수 있습니다.

보통 setXXX는 내부 값을 변경하는 의도이므로 불변 객체의 변경은 withXXX를 사용하는 것이 관례

불변 클래스가 왜 필요한가?

  • 캐시 안정성
  • 멀티 쓰레드 안정성
  • 엔티티의 값 타입
  • 등등

무조건 불변 클래스로 만드는 것이 좋은 것은 아닙니다. 가변 클래스가 더 일반적이며, 값을 변경하면 안되는 특별한 경우에만 사용한다고 생각하면 됩니다.

참고

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.