JAVA
Mutable & Immutable
by orioncsy
2023. 3. 25.
Mutable & Immutable
Mutable Object
개념
- 자바에서 class의 인스턴스로 생성된 이후로 내용이 변경 가능한 객체
- 멀티 스레드 환경에서는 동시성 이슈로 인하여 동기화 처리가 필요하다.
- 대표적으로 ArrayList, HashMap, StringBuilder, StringBuffer 존재
Immutable Object
개념
- 자바에서 class의 인스턴스가 생성된 이후로 내용이 변경 불가능한 객체
- 멀티 스레드 환경에서도 안전하게 사용할 수 있다.
- 대표적으로 String이 존재
- 프로그래머가 커스텀하여 불변 객체 생성 가능
장점
- Thread-safe
- 멀티 스레드 환경에서 공유 자원에 대하여 항상 같은 값을 반환하기 때문에 동기화 과정이 필요 없다.
- 실패 원자적인 메서드 생성 가능
- 가변 객체로 작업 도중 예외가 발생하면 객체 상태가 불안정하지만 불변 객체에서는 그런 문제가 없다.
- Cache, Map, Set에 유리
- Cache, Map, Set에 객체가 변경되면 부가 작업이 필요하지만 불변 객체는 부가 작업을 고려할 필요가 없다.
- 부수 효과를 피해 오류 가능성을 최소화
- 값이 변경되거나 필드 값 설정에 변화가 생기는 부수 효과가 불변 객체에서는 발생하지 않아 오류 최소화
- 타인이 작성한 코드를 예측 가능하게 사용 가능
- GC 성능 향상
- 불변 객체는 할당된 상태 그대로 유지하고 있기 때문에 GC에서 검사할 때 skip할 수 있어 성능 향상
불변 객체 구현
필드가 모두 원시 타입인 경우
- setter 메서드를 생성하지 않고 필드에 final을 붙여 생성
필드에 참조 타입이 있는 경우
- 필드에 있는 참조 타입 또한 불변 객체로 생성해야 가능
필드에 불변 참조 타입 컬렉션이 존재하는 경우
- final을 추가하고 setter를 생성하지 않더라도 주소값을 공유하기 때문에 수정 가능
- 따라서 방어적 복사가 필요
- 생성자에서 참조 타입 컬렉션, 예를 들어 ArrayList를 사용한다면, new ArrayList<>(초기화할 객체)로 선언
- 주입받은 객체와 인스턴스 내의 객체의 주소값을 다르게 하기 위해 메모리에 새로운 객체를 생성하여 초기화
- getter를 사용할 때도 같은 방식으로 하여 다른 주소값으로 객체를 반환하도록 한다.
- Collections.unmodifiableList()을 통해 해당 getter에서 반환할 때 그 객체가 값이 변경되면 예외가 발생
- 그러나 예외처리를 해야 한다.
필드에 가변 참조 타입 컬렉션이 존재하는 경우
- 방어적 복사를 한다고 하더라도 getter를 통해 가져온 ArrayList 컬렉션의 주소 값이 달라도 그 안에 있는 객체들은 같은 주소 값을 갖기 때문에 변경 가능
- 따라서 컬렉션 안에 있는 참조 객체 자체를 불변으로 만들어 주어야 한다.
Reference
https://steady-coding.tistory.com/559