[Java] 불변 객체

jinsung·2일 전

Java

목록 보기
2/5
post-thumbnail

1. 기본형과 참조형의 공유

기본형 (Primitive Type)

하나의 값을 여러 변수에서 절대 공유하지 않음

참조형 (Reference Type)

하나의 객체를 참조값을 통해 여러 변수에서 공유 가능

Member m1 = new Member();
m1.name = "김진슝";

Member m2 = m1;

m2.name = "홍길동";

System.out.println(m1.name); // 홍길동
System.out.println(m2.name); // 홍길동

2. 공유 참조와 사이드 이펙트

사이드 이펙트란?

참조형 객체를 여러 곳에서 공유할 때, 한 곳의 변경이 다른 곳에도 영향을 주는 현상

Member m1 = new Member();
m1.name = "김진슝";

Member m2 = m1;

m2.name = "홍길동";

System.out.println(m1.name); // 홍길동
System.out.println(m2.name); // 홍길동

위 코드를 봤을 때 m2의 이름을 바꿨는데 m1 까지 바뀌었다.
실제로는 둘 다 같은 객체를 가리키기 때문에 (같은 인스턴스 참조) 객체 하나가 변경된 것이다.

해결 방안은?

처음부터 다른 인스턴스를 참조하면 된다.

Member m1 = new Member("김진슝");
Member m2 = new Member("함지성");

하지만 참조값을 공유한다고 해서 컴파일상에서 오류가 뜨는것이 아니기에 막을 방법이 없다.
-> 이때 불변 객체를 사용 :: 객체의 값을 바꿀 수 없게 만들면 된다.


3. 불변 객체 - 도입

객체의 상태(객체 내부 값 : 필드, 멤버 변수)가 변하지 않는 객체를 불변 객체라고 부른다.

public class Member {
	private final String name;
    
    public Member() {
    	this.name = name;
    }
    
    public String getName() {
    	return value
    }
}

객체 내부의 값을 final로 선언하고 setter를 제거해, 생성자를 통해서 값을 설정하고 이후 변경이 불가능하게 했다.

Member m1 = new Member("김진슝");
Member m2 = m1;

m2 = new Member("홍길동");

System.out.println(m1.name); // 김진슝
System.out.println(m2.name); // 홍길동

4. 불변 객체 - 값 변경

불변 객체를 사용하지만 값을 변경해야 되는 경우가 있다면?

public class Member {
    private final int age;

    public Member(int age) {
        this.age = age;
    }

    public Member add(int addAge) {
        int res =  age + addAge;
        return new Member(res);
    }

    public int  getAge() {
        return age;
    }
}
  • 불변 객체는 기존 값을 변경하지 않고 계산 결과를 바탕으로 새로운 객체를 만들어서 반환
  • 불변을 유지하면서 새로운 결과도 반환

Member m1 = new Member(3);
Member m2 = m1.add(10);

System.out.println(m1.getAge()); // 3
System.out.println(m2.getAge()); // 13

5. 불변 객체 - 정리

자바에서 가장 많이 사용되는 String 클래스는 불변 객체이다.
또한 자바에서 기본으로 제공하는 Integer, LocalDate 등 수 많은 클래스가 불변 객체로 설계되어 있다.

모든 클래스가 불변은 아니다

가변 클래스가 더 일반적이고, 불변 클래스는 값을 변경하면 안되는 경우에 만들어서 사용해야 한다.

캐시 안정성, 멀티 쓰레드 안정성, 엔티티 값 타입 등 수 많은 이유로 클래스를 불변으로 설계하곤 한다.

불변 객체 조건

  • 클래스를 final로 만들어 상속을 제한
  • 필드를 private final로 선언
  • setter를 제공하지 않음
  • 생성자에서 모든 값을 설정
  • 상태 변경이 필요하면 새 객체를 반환
profile
Backend Engineer

0개의 댓글