불변 객체
기본형과 참조형의 공유
- 기본형은 하나의 값을 여러 변수에서 절대로 공유하지 않는다.
- 참조형은 하나의 객체를 참조 값을 통해 여러 변수에서 공유할 수 있다.
- 참조형은 같은 참조 값을 통해 같은 인스턴스를 참조할 수 있다.
- ★자바는 값을 항상 복사해서 대입한다★
- 기본형은 값을, 참조형은 참조 값을 복사해서 대입한다.
공유 참조와 사이드 이펙트
- 사이드 이펙트 : 프로그래밍에서 어떤 계산이 주된 작업 외에 추가적인 부수 효과를 일으키는 것.
- 보통 부정적인 의미로 사용되며 특정 부분에서의 변경이 의도치않게 다른 부분에 영향을 미치는 경우
- 디버깅이 어려워지고 코드의 안정성이 저하된다.
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()는 원본 객체의 상태가 그대로 유지됨을 강조하면서 변경사항을 새 복사본에 포함한다.
- 클래스를 불변으로 설계하는 이유?
- 캐시 안정성
- 멀티 쓰레드 안정성
- 엔티티의 값 타입
출처: [인프런 김영한 실전 자바 - 중급편]
김영한의 실전 자바 - 중급 1편 강의 | 김영한 - 인프런
김영한 | 실무에 필요한 자바의 다양한 중급 기능을 예제 코드로 깊이있게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을
www.inflearn.com
'Java > [인프런 김영한 실전 자바 - 중급편]' 카테고리의 다른 글
[인프런 김영한 실전 자바 - 중급편] 날짜와 시간 (1) | 2024.07.21 |
---|---|
[인프런 김영한 실전 자바 - 중급편] 열거형 - ENUM (0) | 2024.07.19 |
[인프런 김영한 실전 자바 - 중급편] 래퍼, Class 클래스 (0) | 2024.07.19 |
[인프런 김영한 실전 자바 - 중급편] String 클래스 (3) | 2024.07.18 |
[인프런 김영한 실전 자바 - 중급편] Object 클래스 (1) | 2024.07.18 |