Java/[인프런 김영한 실전 자바 - 중급편]

[인프런 김영한 실전 자바 -중급편] 불변 객체

h2boom 2024. 7. 18. 17:11

불변 객체

기본형과 참조형의 공유

  • 기본형은 하나의 값을 여러 변수에서 절대로 공유하지 않는다.
  • 참조형은 하나의 객체를 참조 값을 통해 여러 변수에서 공유할 수 있다.
    • 참조형은 같은 참조 값을 통해 같은 인스턴스를 참조할 수 있다.
  • ★자바는 값을 항상 복사해서 대입한다★
    • 기본형은 값을, 참조형은 참조 값을 복사해서 대입한다.

공유 참조와 사이드 이펙트

  • 사이드 이펙트 : 프로그래밍에서 어떤 계산이 주된 작업 외에 추가적인 부수 효과를 일으키는 것.
    • 보통 부정적인 의미로 사용되며 특정 부분에서의 변경이 의도치않게 다른 부분에 영향을 미치는 경우
    • 디버깅이 어려워지고 코드의 안정성이 저하된다.
Address a = new Address("서울");
Address b = a; //변수 a,b는 서로 같은 객체를 참조하고 있다.

b.setValue("부산"); // b가 참조하고 있는 값을 변경했는데 사이드 이펙트가 발생.. a에 영향
  • 코드로만 봤을 때는 인스턴스를 생성하지 않아도 되기에 메모리와 성능에서 효율적이다.
    • 참조형에서 같은 인스턴스를 참조하는 경우 사이드 이펙트가 발생할 수 있다.
Address a = new Address("서울");
Address b = new Address("서울");
  • 이전 예시에서 사이드 이펙트를 해결하기 위해서는 서로 다른 인스턴스를 참조하면 된다.
    • 하지만 여러 변수가 하나의 객체를 공유하는 것을 막을 수 있는 방법이 없다.
    • 사이드 이펙트의 더 근본적인 원인은 공유된 객체의 값을 변경한 것.

불변 객체

  • 사이드 이펙트 문제를 해결하기 위해서 객체를 공유(참조 값 대입)하는 것은 막지 못하지만 공유된 객체의 값을 변경하지 못하게 설계한다면 해결된다.
  • 불변 객체 : 객체의 상태(필드)가 변하지 않는 객체를 의미한다.
  • 자바에서 자주 사용하는 String, Integer, LocalDate 등 많은 클래스가 불변으로 설계되어 있다.

 

public class ImmutableAddress {
//객체의 상태가 변하지 못하게 필드를 final로 선언한다.
    private final String value;

    public ImmutableAddress(String value) {
        this.value = value;
    }


    public String getValue() {
        return value;
    }

    //final 변수로 생성자에서 초기화를 하기 때문에 setter를 사용하지 못한다.
}
  • 불변 객체로 만들어주기 위해서 필드를 final로 선언해 수정하지 못하도록 한다.
    • 생성자 외에 값을 초기화 할 방법이 없으므로 final이 없어도 상관 없다. (final을 통해의도를 명확히 하기 위함)
    • 불변 객체로 만들기 위해서 Setter를 제공해서는 안된다.
  • 불변이라는 단순한 제약을 통해 사이드 이펙트를 방지할 수 있다!!
    • 객체의 공유 참조는 막을 수 없다.
      • 객체를 공유하는 중 객체의 값을 변경하면 사이드 이팩트가 발생한다.
    • 사이드 이펙트가 발생하면 안되는 상황에서는 불변 객체를 만들어 사용하면 된다.
      • 불변 객체는 값을 변경할 수 없기에 사이드 이펙트가 발생할 수 없다.
      • 불변 객체의 값을 변경하고 싶다면 새로운 불변 객체를 생성해야 한다.

 

가변(Mutable) 객체 : 처음 만든 이후 상태가 변할 수 있다.
불변(Immutable) 객체 : 처음 만든 이후 상태가 변하지 않는다.

 

 

//가변 객체의 값 변경
public void add(int addValue) {
	value = value + addValue;
}


//불변 객체의 값 변경
public ImmutableObj add(int addValue) {
	return new ImmutableObj(value + addValue);
}
  • 가변 객체는 add()를 호출 시 기존 값을 변경하기에 기존 값이 없어진다.
  • 불변 객체는 값을 변경할 수 없기 때문에 기존 값을 변경하지 않고 새로운 인스턴스를 만들어서 반환해준다.
    • 불변도 유지하면서 새로운 값을 받을 수 있다.
    • 불변 객체에서 변경과 관련된 메소드들은 보통 객체를 새로 만들어서 리턴하기 때문에 꼭 반환 값을 받아야한다! 
  • 불변 객체를 사용하면 값이 변경될 때마다 새로운 인스턴스를 생성해야하므로 값이 자주 변경되는 경우에는 성능상 불리하므로 가변 객체가 나을 수도 있다.

 

  • 보통 불변 객체의 값을 변경하는 메소드에는 setXxx()보다는 withXxx()로 메소드명을 작성한다.
    • setXxx()는 내 객체의 값을 변경할 때 사용한다.
    • withXxx()는 원본 객체의 상태가 그대로 유지됨을 강조하면서 변경사항을 새 복사본에 포함한다.

 

  • 클래스를 불변으로 설계하는 이유?
    • 캐시 안정성
    • 멀티 쓰레드 안정성
    • 엔티티의 값 타입

출처: [인프런 김영한 실전 자바 - 중급편]

https://www.inflearn.com/course/%EA%B9%80%EC%98%81%ED%95%9C%EC%9D%98-%EC%8B%A4%EC%A0%84-%EC%9E%90%EB%B0%94-%EC%A4%91%EA%B8%89-1/dashboard

 

김영한의 실전 자바 - 중급 1편 강의 | 김영한 - 인프런

김영한 | 실무에 필요한 자바의 다양한 중급 기능을 예제 코드로 깊이있게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을

www.inflearn.com