[JAVA] 불변 객체
[JAVA] 불변 객체
자바 데이터 타입 분류
- 기본형(Primitive Type): 값을 직접 저장. 공유 X
- 참조형(Reference Type): 객체의 참조값을 저장. 공유 O
기본형은 값 복사
1
2
3
4
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 10
b = a는 값을 복사함 →a,b는 완전히 별개
참조형은 참조값 복사 (공유 발생)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//참조형 변수는 하나의 인스턴스를 공유한다.
//즉, 참조형 변수는 같은 참조값(x001)을 통해 같은 인스턴스를 참조
Address a = new Address("서울"); //새로운 객체 참조
Address b = a; //참조값(x001) 복사해 전달 (참조값의 공유를 막을 방법 X)
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("b 를 부산으로 변경");
b.setValue("부산");
System.out.println("a = " + a); //사이드 이펙트 발생 -> 특정부분 변경이 예기치 않게 다른 부분에 영향을 줌 (나는 b만 바꾸고 싶었는데?)
System.out.println("b = " + b);
//참조형 변수는 참조값을 통해 같은 객체(인스턴스)를 공유
a,b가 같은 객체를 참조 → 하나 변경 시 사이드 이펙트 발생
사이드 이펙트란?
- 의도하지 않은 값 변경 효과
b만 바꾸려 했는데a도 바뀜 → 디버깅 어려움
해결 1: 객체 공유 안 하기
1
2
3
Address a = new Address("서울");
Address b = new Address("서울");
//a와 b가 서로다른 인스턴스 참조
- 완전히 다른 객체 → 공유 안 됨
- 하지만 공유 방지 강제할 방법 없음
객체 공유를 막을 수 없는 이유
1
2
Address a = new Address("서울");
Address b = a; // 정상 문법, 막을 방법 없음
- 참조값은 언제든 다른 변수에 복사 가능
- 공유 자체는 막을 수 없음 → “값 변경”을 막는 게 핵심
해결 2: 불변 객체로 설계
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//불변 객체 예제 (불변 클래스)
public class ImmutableAddress {
private final String value; //final로 선언해 내부 값 변경 불가능
public ImmutableAddress(String value) {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public String toString() {
return "ImmutableAddress{" +
"value='" + value + '\'' +
'}';
}
}
- 값 변경 메서드 제거 (
setValue()없음) value필드는final- 변경이 필요하면 새 객체 생성
불변 객체 사용 시
1
2
3
4
5
6
7
8
9
10
11
12
13
ImmutableAddress a = new ImmutableAddress("서울");
ImmutableAddress b = a; //참조값 대입을 막을 수 없다
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("b -> 부산");
//b.setValue("부산"); //컴파일 오류 발생 setValue 없어 변경 불가
b = new ImmutableAddress("부산"); //신규 생성
System.out.println("a = " + a);
System.out.println("b = " + b);
//final로 단순한 제약을 만들어 사이드 이펙트라는 큰 문제를 막음
//불변객체의 값을 변경하고 싶으면 새로운 불변객체 생성
- 공유는 되지만 값은 절대 안 바뀜
- 사이드 이펙트 완전 차단
가변 객체 vs 불변 객체
| 구분 | 가변 객체 (Address) |
불변 객체 (ImmutableAddress) |
|---|---|---|
| 값 변경 가능 | ✅ setValue() 있음 |
❌ 없음 |
| 사이드 이펙트 발생 가능성 | 높음 | 없음 |
| 공유 참조 안전성 | 낮음 | 높음 |
불변 객체 활용 예
1
2
3
4
//불변 객체는 값을 변경하면 안됨, 기존 값에 새로운 값을 더해야 함
public ImmutableObj add(int addValue) {
return new ImmutableObj(value + addValue); //객체는 기존값을 변경하지 않고 계산값을 새로운 객체로 만들어 반환
}
- 기존 객체는 유지
- 새 객체에 결과 저장 → 함수형 스타일
- 참조형은 공유되기 때문에 사이드 이펙트 주의
- 불변 객체는 공유돼도 안전 → 값을 변경할 수 없기 때문
- 자바 기본 클래스(
String,Integer,LocalDate) 대부분 불변 객체 - 불변 객체는 안정성, 멀티스레드, 캐시, 값 타입 등에서 유용
This post is licensed under
CC BY 4.0
by the author.