Java

Java, Immutable 불변 객체란?

greenyellow-s 2025. 4. 2. 15:00
728x90
반응형

immutable 불변 객체 

객체 생성 이후 내부 상태가 변하지 않는, 변경할 수 없는 객체

 

대표적으로 Java String, Integer, Long, Double 있다.

 


사용하는 이유

동시성 문제 해결

  • 멀티스레드 환경에서 가변 객체를 공유하면 예상치 못한 동작이 발생할 수 있다. 하지만 불변 객체는 상태가 변하지 않기 때문에 여러 스레드에서 안전하게 공유할 수 있다.

 

안정성과 예측 가능성 증가

  • 불변 객체는 생성된 후 값이 변하지 않으므로 한 번 설정된 상태를 유지할 수 있다. 이 덕분에 프로그램의 흐름을 더 쉽게 예측할 수 있다.

 

참조 투명성 유지

  • 불변객체는 항상 같은 입력에 대해 같은 출력을 보장한다. 즉, 순수 함수에 적합하므로 함수형 프로그래밍에서도 많이 사용된다.

 

불필요한 방어적 복사 제거

  • 가변 객체를 사용할 경우, 객체가 변경되지 않도록 복사본을 만들어야 하는 경우가 많다. 하지만 불변 객체를 사용하면 복사할 필요 없이 참조만 공유해도 안전하다.

 

해싱과 캐싱에 유리

  • 불변 객체는 값이 변하지 않으므로 한 번 해시 값을 계산하면 변경될 일이 없다. 따라서 HashMao, HashSet, ConcurrentHashMap 같은 자료구조에서 불변 객체를 키로 사용하면 효율적이다.

적용 예시

   String, Integer, BigDecimal, LocalDateTime

   @Value 활용한 DTO(Lombok)

   record(Java 14 +)


1. 불변 클래스

public final class ImmutablePerson {
    private final String name;
    private final int age;

    public ImmutablePerson(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

 

 

  • final 키워드로 클래스 상속 방지
  • 모든 필드를 private final로 선언
  • 값을 변경할 수 있는 setter 메서드 없음
  • 생성자를 통해서만 값을 설정

2. 불변 객체의 장점: 동시성 문제 해결

public class TestThreadSafety {
    public static void main(String[] args) {
        ImmutablePerson person = new ImmutablePerson("Alice", 30);

        Runnable task = () -> {
            System.out.println(Thread.currentThread().getName() + " - Name: " + person.getName());
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
    }
}

 

 

여러 스레드에서 person 객체를 동시에 참조해도 데이터가 변하지 않기 때문에 안전합니다.

 

 

가변 객체였을 경우,

private String name;
private int age;

 

  • 값이 언제든 변경될 수 있음
  • 여러 스레드가 동시에 접근하면 값이 바뀔 가능성이 있음
  • 동기화 처리가 필요할 수 있음
  • 값이 바뀔 가능성이 있어 예측이 어려움

3. 불변 객체 LocalDate 사용

import java.time.LocalDate;

public class ImmutableExample {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2023, 4, 2);

        // 새로운 날짜를 생성하지만 기존 객체는 변경되지 않음
        LocalDate newDate = date.plusDays(10);

        System.out.println("원본 날짜: " + date);      // 2023-04-02
        System.out.println("변경된 날짜: " + newDate); // 2023-04-12
    }
}

 


4. Lombok의 @Value를 활용한 불변 객체 생성

import lombok.Value;

@Value
public class ImmutableUser {
    String username;
    int age;
}

 


5. Java 14+ record를 이용한 불변 객체

 

public record PersonRecord(String name, int age) {}

 

PersonRecord p = new PersonRecord("Bob", 25);
System.out.println(p.name()); // Bob
  • 불변 객체 자동 생성
  • 생성자, getter, toString(), equals(), hashCode() 자동 생성

 

  • 불변성(Immutable) 보장 → 필드 값 변경 불가
  • 자동 getter 제공 → name() 메서드가 name 값을 반환
  • equals(), hashCode() 자동 생성 → 객체 비교에 유용
  • toString() 자동 생성 → 디버깅이 쉬움
728x90
반응형