Immutable Object (불변객체)

귀찮Lee·2022년 7월 24일
0

Java

목록 보기
15/15

◎ 불변 객체

  • 불변 객체

    • 생성 후 그 상태를 바꿀 수 없는 객체, 재할당은 가능하지만 내부 데이터를 변경할 수 없는 객체
    • 장점
      • 복제나 비교를 위한 조작을 단순화 할 수 있고, 성능 개선에도 도움을 준다.
      • 멀티 스레드 프로그래밍에 용이 (한 스레드에서 값을 변경하여 다른 스레드에 영향을 미치는 것을 방지)
  • 배경

    • 대부분의 객체 지향 언어에서 객체는 참조(reference) 형태로 전달한다.
    • 보통 객체를 복사할 때는 객체 전체를 복사하는 것이 아니라, 참조값만을 복사하고 끝난다. (보통 참조값이 그 객체 자체보다 훨씬 작기 때문에)
      • 이것이 의도한 동작이 아니라면 대참사가 일어나기 쉽다.
      • 참조값만을 복사한 변수에서 변경한다면, 원래 있었던 변수에서도 같은 변경이 일어남 (같은 객체를 참조하고 있기 때문에)

◎ 불변 객체 만들기

  • 모든 클래스 변수를 private와 final로 선언하라
  • 객체를 생성하기 위한 생성자 또는 정적 팩토리 메소드를 추가
  • 참조에 의해 변경가능성이 있는 경우 방어적 복사를 이용하여 전달
  • 클래스를 final로 선언 (상속을 금지 시킴)

◎ 불변 객체 예시

  • 일반적인 불변 객체

    • java의 일반적인 타입만 있는 경우, final 키워드를 이용해 수정을 불가하게 만듦
    class ImmutablePerson {
        private final int age;
        private final int name;
    
        public ImmutablePerson(int age, int name) {
            this.age = age;
            this.name = name;
        }
    }
  • 참조 타입이 있는 경우

    • 참조 객체를 getter로 가져와서 수정 할수 있음
    • 참조 객체도 불병 객체이어야 함
    public class Animal {
    
        private final Age age;
    
        public Animal(final Age age) {this.age = age;}
        public Age getAge() {return age;}
    }
    
    class Age {
    
        private int value;
    
        public Age(final int value) {this.value = value;}
        public int getValue() {return value;}
    }
  • Array일 경우

    • Array를 가져와서 내부 자료를 바꿀 수 있음
    • 초기 저장할 때, copy를 해서 저장
    • Array를 가져올 때는 clone을 해서 가져옴
      (참조값을 외부에서 모르게하여 내부값을 수정 못하게 함)
public class ArrayObject {

    private final int[] array;

    public ArrayObject(final int[] array) {
        this.array = Arrays.copyOf(array,array.length);
    }

    public int[] getArray() {
        return (array == null) ? null : array.clone();
    }
}
  • List인 경우

    • List를 가져와서 내부 자료를 바꿀 수 있음
    • 생성시, 새로운 List를 만들어 값을 복사
    • getter를 통해 값 추가/삭제가 불가능하도록 Collection의 unmodifiableList 메서드를 사용
    public class ListObject {
    
        private final List<Animal> animals;
    
        public ListObject(final List<Animal> animals) {
            this.animals = new ArrayList<>(animals);
        }
    
        public List<Animal> getAnimals() {
            return Collections.unmodifiableList(animals);
        }
    }

◎ 참고 자료

profile
배운 것은 기록하자! / 오류 지적은 언제나 환영!

0개의 댓글