네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

# 변경 가능성을 최소화하라.

## 불변 클래스(Immutable Class) ?

- 해당 객체의 내부적인 값들을 변경할 수 없는 클래스를 의미한다. 불변 클래스는 해당 객체가 파괴되는 순간까지 절대 달라지지 않는다.

- 불변 클래스는 가변 클래스보다 설계하고 구현하기 쉽고, side-effect로부터 안전

- 예) String, Wrapper Class, BigInteger, BigDecimal - 설계 구현 사용이 쉽다.

- 오류의 여지가 적고 안전하다.

 

## 1. 불변 클래스의 5가지 규칙

1) 객체의 상태를 변경하는 메서드(변경자, setter)를 제공하지 않는다.

2) 클래스를 확장할 수 없게 한다. - extend (X)

3) 모든 필드를 final로 선언한다.

4) 모든 필드를 private로 선언한다.

5) 자신 외에는 내부의 가변 컴포넌트에 접근할 수 없도록 한다.

 

## 2. 불변 객체의 장점

0) 단순

- 불변 객체는 생성된 시점부터 파괴될 때까지 그대로 유지한다.

 

1) 근본적으로 스레드에 안전

- 여러 스레드가 동시에 사용해도 불변 객체이기 때문에 다른 스레드에 영향을 주지 않아 안전하게 공유하고 사용할 수 있다.

- 동기화할 필요가 없다.

 

2) 불변 객체는 안심하고 공유가 가능

- 스레드 간 영향을 주고 받을 수 없기 때문

- 방어적 복사도 필요없다> clone 메서드 복사 생성자 필요 없다.

- String 클래스의 복사 생성자는 되도록 사용하지 말자

 

3) 한번 만든 인스턴스는 최대한 재활용이 가능

- 자주 사용하는 인스턴스를 생성하여, 정적 팩터리를 제공할 수 있다.

 

4) 불변 객체는 자유롭게 공유할 수 있음은 물론, 불변 객체끼리는 내부 데이터를 공유할 수 있음

 

5) 객체를 만들 때 다른 불변 객체들을 구성요소로 사용하면 이점이 많다.

- 구조가 복잡해도 불변식 유지가 수월

 

6) 불변 객체는 그 자체로 실패 원자성을 제공한다.

- 실패 원자성: 메서드에서 예외가 발생한 후에도 그 객체는 메서드 호출 전 상태와 같은 유효한 상태를 가진다.

 

## 3. 불변 객체의 단점

- 값이 다르면 반드시 독립된 객체로 만들어야 한다. 값의 가짓수가 많으면 이를 모두 만드는데 큰 비용이 필요하다.

 

1) 흔히 쓰일 다단계 연산들이 예측이 될 때

- 다단계 연산 속도를 높여주는 가변 동반 클래스를 package-privated로 둔다.

- BigInteger는 연산 속도를 높여주는 동반 클래스로 package-privated로 되어있는 MutableBigInteger/SignedMutableBigInteger/BigSieve를 사용할 것으로 예상

 

2) 예측이 되지 않을 때

- 다단계 연산 속도를 높여주는 가변 동반 클래스를 public으로 둔다.

- 예) StringBuilder/StringBuffer: String 클래스의 연산 속도를 높이기 위함

 

## 4. 불변 클래스를 만드는 설계 방법

1. final 클래스로 상속을 막는다.

2. 정적 팩터리를 제공하는 방법

- 모든 생성자를 private 혹은 package-private로 만들고 public 정적 팩터리를 제공한다. (캐싱 기능 추가도 가능하다.) public이나 protected 생성자가 없으니 다른 패키지에서는 이 클래스를 확장하는 게 불가능하기 때문이다.

 

## 정리

- 모든 클래스를 불변으로 만들 수는 없기 때문에 클래스라도 변경 가능한 부분을 최소한으로 줄이는 것이 좋다.

- 클래스가 꼭 필요한 경우가 아니면 불변이어야 한다.

- 다른 합당한 이유가 없다면 모든 필드는 private final이어야 한다.

- 생성자는 불변식 설정이 모두 완료된 초기화가 완벽히 끝난 상태의 객체를 생성해야 한다.

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !