Clean code적으로나 java 언어를 공부하면서 클래스와 필드, 메소드는 불변성을 유지해야 한다는 문구를 많이 접했었다. 그 상태가 변하지 않게 한다.라는 뜻을 개발 측면에서 정확히 그 의도를 파악하기 위해 불변성의 의도와 올바른 사용법을 알고자 한다.
인스턴스가 생성된 이후 그 상태가 변하지 않는다.
클래스나 변수, 메소드에 불변성을 주기 위해서는 final 키워드를 사용한다.
final은 변수에 사용되면 값을 변경할 수 없는 상수가 되며
메서드에 사용되면 오버라이딩(overriding)을 할 수 없게 된다.
클래스에 사용되면 자신을 확장하는 자식 클래스를 정의하지 못하게 된다.
변수 선언 시 앞에 final을 붙여보자. 기본적으로 final은 초기화 후에 값을 변경할 수 없다.
class Test {
final String text;
boolean status = true;
if(status) { // final 변수 초기화
text = "hello";
} else {
text = "bello~";
}
Test() { //final 변수 초기화
text = "hello";
}
}
static{} 안에서 초기화가 가능하다.static final String text;
static {
text = "hello";
}
final List<String> list = new ArrayList<>(); // 불변 변수 list는 변경 불가
list.add("Hello");
list.add("bello");
... // 그러나 list 내부 변수는 변경이 가능하여 추가가 가능한 것
불변 객체를 생성하기 위해서는 다음과 같은 규칙에 따라서 클래스를 생성해야 한다.
final로 선언하라private와 final로 선언하라생성자 또는 정적 팩토리 메소드를 추가하라불변성을 줘서 얻을 수 있는 장점은 다음과 같다.
- Thread-Safe하여 병렬 프로그래밍에 유용하며, 동기화를 고려하지 않아도 된다.
- 실패 원자적인(Failure Atomic) 메소드를 만들 수 있다.
- Cache나 Map 또는 Set 등의 요소로 활용하기에 더욱 적합하다.
- 부수 효과(Side Effect)를 피해 오류가능성을 최소화할 수 있다.
- 다른 사람이 작성한 함수를 예측가능하며 안전하게 사용할 수 있다.
- 가비지 컬렉션의 성능을 높일 수 있다.
결국 불변성을 유지해야 하는 이유는 변경 가능성을 최소화하기 위함이라는 것을 알 수 있었다.
https://alexander96.tistory.com/16
https://mangkyu.tistory.com/131
https://7942yongdae.tistory.com/147
Q1. 왜 final 키워드를 붙이면 thread-safe 한가요?
Q2. 컬렉션의 불변을 지키기 위한 방법은 없나요?
Q3. 그렇다면 모든 변수에 final 키워드를 붙여야 하나요?
Q4. final 키워드의 단점은 없나요?