자바에서 객체를 생성할경우 해당 객체를 수정할 수 있다.
이럴경우 내부 상태가 변경되기때문에 예측 가능한 동작 상태에서 벗어나고 이는 코드 안정성을 떨어뜨리게 된다.
또한 가변객체일경우 서로 여러 스레드를 동시에 사용하기에도 불편하고 위험하다.
그래서 이와 반대로 불변객체(Immutable Object)가 존재한다
한번 생성된 뒤로부터 내부 상태가 변경되지 않는 객체를 말한다.
모든 필드는 초기에 설정되고 그 이후로는 변경되지 않는다
먼저 final이 있어야한다
그다음 객체안에 setter가 있으면 안된다 (setter가 있을경우 값을 변경할 수 있기때문)
public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
위의 코드는 Person이라는 객체를 불변 객체로 만들었다
먼저 클래스에 final을 넣어 불변하게 만들고 값또한 private로 필드를 제한한다음 final을 넣어 상수로 해주었다.
그리고 메서드는 get만 구현하여 읽기만 가능하게 만들었다
그 다음 equals()를 재정의 하여 불변객체임을 증명하는 메서드로 다시 작성해주었고
hashCode()도 재정의하여 동일한 내용을 가지는 객체가 동일한 해시코드를 반환하는지를 확인시켜주었다
배열 또한 필드를 제한하거나 final을 사용하여 불변으로 만들 수 있다.
또한 깊은 복사를 이용해서 불변으로 만들 수 있다.
public class ImmutableArr {
private final int[] arr;
public ImmutableArr(int[] arr) {
this.arr = Arrays.copyOf(array, array.length);
}
}
list에서는 Collections.unmodifiableList()메서드를 이용해 불변으로 만들 수 있었다.
그리고 java9에서는 List.of()를 이용해 불변으로 만들 수 있다.
public class ImmutableList {
private final List<Integer> list;
public ImmutableList(List<Integer> list) {
this.list = Collections.unmodifiableList(list);
/*
Collections.unmodifiableMap();
Collections.unmodifiableSet();
*/
}
public List<Integer> getList() {
//변경 방지를 위해 복사본 사용
return List.copyOf(list);
}
}
List<String> list = List.of("test","immutable");
list.add("plus") //에러 발생
/*
Map.of
Set.of
*/