
불변객체 왜 사용 ? 공유된 객체의 값을 변경한 부분을 잘 제어하기 위해 우리는 불변객체라는 녀석을 사용할 수 있다.
객체의 상태가 변하지 않는 객체를 불변객체(Immutable Object)라고 한다.
그럼, 이전 글에서 만들었던 Drink 클래스와는 달리...
2024.08.13 - [분류 전체보기] - 기본형과 참조형
기본형과 참조형
우리가 자바의 데이터 타입은 기본형과 참조형으로 나눌 수 있다. 두 타입의 특징은 다음과 같다.**기본형**: 하나의 값을 여러 변수에서 절대로 공유 X**참조형**: 하나의 객체를 참조값을 통해
jinhadev.tistory.com
상태가 변하지 않는 ImmutableDrink 불변 클래스를 만들어보자.
package lang.immutable;
public class ImmutableDrink {
private final String name;
public ImmutableDrink(String name) {
this.name = name;
}
public String getValue() {
return name;
}
@Override
public String toString() {
return "Drink{" +
"name='" + name + '\'' +
'}';
}
}
final로 선언된 name 변수는 이제 setValue method를 사용할 수 없다!
즉 생성자로만 값을 셋팅할 수 있게하고 직접적으로 필드 값을 변경할 수 없게만 해주면 이 자체로 불변객체가 된다는걸 알 수 있다.
package lang.immutable;
public class RefImmutableEx {
public static void main(String[] args) {
ImmutableDrink drink1 = new ImmutableDrink("Americano");
ImmutableDrink drink2 = drink1;
System.out.println("drink1 = " + drink1);
System.out.println("drink2 = " + drink2);
// 더이상 drink2를 set 할 수 있는 방법이 없다. ImmutableDirnk Class-> setValue method 없음.
drink2.setValue("Latte"); // compile Error
}
}
위에서 ImmutableDrink 클래스에선 이제 값을 변경할 수 있게 set 할 수 있는 방법이 존재하지 않는다.
왜냐면 여기서 setValue함수는 더이상 없으니 사용하려고하면 컴파일 오류가 발생한다는걸 알 수 있다.
그럼 이렇게 사용하면 얻게되는 장점은 ??
>>> ImmutableDrink 이 클래스 내부를 잘 모르는 개발자도 불변객체라는걸 쉽게 인지 할 수 있다는게 큰 장점이다.
뭐, b = new Address("Latte"); 와 같은 코드로 새로운 객체를 다시 생성해서 임의로 내가 변경할 수는 있다.
다만, 내가 사용하려는 객체가 불변 객체인지 아닌지에 따라 불변객체라면 사이드 이펙트가 발생할 여지가 크게 줄어들 수 있다는게 큰 장점이란걸 말해주고 싶다.
이번엔 그러면, 날짜를 변경하는 불변 객체를 만들어보자.
package lang.immutable.date;
public class ImmutableMyDate {
private final int year;
private final int month;
private final int day;
public ImmutableMyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
public ImmutableMyDate withYear(int newYear) {
return new ImmutableMyDate(newYear, month, day);
}
public ImmutableMyDate withMonth(int newMonth) {
return new ImmutableMyDate(year, newMonth, day);
}
public ImmutableMyDate withDay(int newDay) {
return new ImmutableMyDate(year, month, newDay);
}
public ImmutableMyDate withDate(int newYear, int newMonth, int newDay) {
return new ImmutableMyDate(newYear, newMonth, newDay);
}
@Override
public String toString() {
return "ImmutableMyDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
ImmutableMyDate Class로 연/월/일을 각각 변경하고 새로운 객체를 리턴하는 함수 withYear, withMonth,withDate 와 연/월/일 한꺼번에 변경할 수 있도록 도와주는 withDate 함수를 만들어 사용해보자.
package lang.immutable.date;
public class ImmutableMyDateMain {
public static void main(String[] args) {
ImmutableMyDate myDate1 = new ImmutableMyDate(2024, 8, 14);
ImmutableMyDate myDate2 = myDate1;
System.out.println("myDate 1 = " + myDate1); // myDate 1 = ImmutableMyDate{year=2024, month=8, day=14}
System.out.println("myDate 2 = " + myDate2); // myDate 2 = ImmutableMyDate{year=2024, month=8, day=14}
myDate2 = myDate2.withYear(2025);
myDate2 = myDate2.withMonth(10);
myDate2 = myDate2.withDay(30);
System.out.println("myDate 1 = " + myDate1); // myDate 1 = ImmutableMyDate{year=2024, month=8, day=14}
System.out.println("myDate 2 = " + myDate2); // myDate 2 = ImmutableMyDate{year=2025, month=10, day=30}
myDate2 = myDate2.withDate(2030, 01, 05);
System.out.println("myDate 1 = " + myDate1); // myDate 1 = ImmutableMyDate{year=2024, month=8, day=14}
System.out.println("myDate 2 = " + myDate2); // myDate 2 = ImmutableMyDate{year=2030, month=1, day=5}
}
}
println으로 각각 출력한 결과를 살펴보면 변경하지 않은 객체 myDate1은 year=2024, month=8, day=14로 항상 같으며
변경하려고자 하는 myDate2 객체 값은 내가 변경하고자 하는 값으로 잘 변경되는걸 확인할 수 있었다.
Java 뿐만아니라, 내가 자주 사용한 언어인 JavaScript도 이 불변객체에 대한 개념을 잘 몰랐을때 이 참조값을 변경하는 문제로 꽤나 힘들었던 경험이 떠오른다. 더군다나 Typescript가 도입되기 이전에 JavaScript는 타입이 존재하지 않으니.. 디버깅하기가 너무 어려웠었다.
'개발 > Java' 카테고리의 다른 글
| Enum (0) | 2024.08.15 |
|---|---|
| String Class (0) | 2024.08.14 |
| 기본형과 참조형 (0) | 2024.08.13 |
| toString 메서드 파헤치기 (3) | 2024.08.13 |
| Object 클래스 (0) | 2024.08.12 |