Java Immutable Object

박은빈·2023년 5월 18일
0

자바

목록 보기
23/25

자바에서 객체를 생성할경우 해당 객체를 수정할 수 있다.
이럴경우 내부 상태가 변경되기때문에 예측 가능한 동작 상태에서 벗어나고 이는 코드 안정성을 떨어뜨리게 된다.
또한 가변객체일경우 서로 여러 스레드를 동시에 사용하기에도 불편하고 위험하다.

그래서 이와 반대로 불변객체(Immutable Object)가 존재한다

불변객체란

한번 생성된 뒤로부터 내부 상태가 변경되지 않는 객체를 말한다.
모든 필드는 초기에 설정되고 그 이후로는 변경되지 않는다

특징

  1. 상태의 불변성 : 한번 설정되면 변경이 불가능하기때문에 객체의 상태는 객체의 수명동안 동일하게 유지된다.
  2. 스레드 안정성 : 불변 객체는 여러 스레드에서 동시에 사용해도 안전하다. 동기화를 고려할 필요가 없기때문에 동기화 문제를 방지할 수 있다
  3. 객체 재사용 : 불변 객체는 안전하게 공유될 수 있으므로 동일한 값을 갖는 객체는 여러 곳에서 재사용될 수 있다.
  4. 보안 : 불변 객체는 내부 상태를 변경할 수 없기때문에 보안 취약성을 줄일 수 있다.

생성 방법

객체

먼저 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
*/
profile
안녕하세요

0개의 댓글