Language/Java

[JAVA] 불변객체

leegeonwoo 2024. 6. 24. 22:55
  • 기본형: 하나의 값을 여러 변수에서 절대로 공유하지 않는다
  • 참조형: 하나의 객체를 참조값을 통해 여러 변수에서 공유할 수 있다

참조형 변수는 참조값을 복사해서 대입하기때문에 여러변수에서 얼마든지 같은 객체를 공유할 수 있다.
객체의 공유는 필요할 때도 있지만 때로는 객체의 공유로 인하여 사이드 이펙트를 만드는 경우도있다.

Ex)예상치 않은 참조로 인해서 기존의 참조변수의 값이 변경되어 사이드이펙트가 발생되는경우

Address addressA = new Address();  
Address b = addressA;

위 코드가 객체의 공유를 의미하며 객체의 공유는 아래와 같은 사이드 이펙트를 유발할 수 있다.

public static void main(String[] args) {  
    Address addressA = new Address();  
    addressA.setAddress("서울");  
    System.out.println("addressA = " + addressA);  

    Address addressB = addressA;  
    addressB.setAddress("부산");  
    System.out.println("addressA = " + addressA);  
    System.out.println("addressB = " + addressB);  
}
addressA = Address{address='서울'}
addressA = Address{address='부산'}
addressB = Address{address='부산'}

개발자의 의도는 addressB의 주소만 부산으로 변경하려했지만 객체는 주소를 참조하는 형태를 이루고있기 때문에 addressA의 주소도 부산으로 바뀐 실행결과를 확인할 수 있다.

자바문법상으로 객체가 공유됨을 막을 수 없고, 객체의 공유는 큰 문제를 가져올 수 있기때문에 신중히 해야한다.

결론적으로 보자면, 객체의 공유자체는 문제가 되지 않지만 공유 후에 해당 객체의 값을 변경하였을 때 사이드 이펙트가 발생하게 되는 것이다.

즉 객체의 공유는 허용하더라도 값에 변경을 막기만 하면 자바의 문법만으로도 충분히 객체의 공유에대한 사이드이펙트 가능성을 막을 수 있다.

 

값에 변경을 막기위해서는 어떻게해야할까?

  • 처음 필드의 값을 선언할 때는 생성자만으로 선언
  • 해당 객체의 setXXX메서드 선언하지 않음
  • 멤버변수에 final키워드 사용
    위의 과정을 통하여 불변객체를 생성함으로써 사이드 이펙트문제를 미리 막을 수 있다.
public class ImmutableMain1 {  

    public static void main(String[] args) {  
        Address addressA = new Address("서울");  
        System.out.println("addressA = " + addressA);  

        Address addressB = addressA;  
        addressB = new Address("부산");  
        System.out.println("addressA = " + addressA);  
        System.out.println("addressB = " + addressB);  
    }  
}  

class Address{  
    private String address;  

    public Address(String address) {  
        this.address = address;  
    }  

    public String getAddress() {  
        return address;  
    }  

    @Override  
    public String toString() {  
        return "Address{" + "address='" + address + '\'' + '}';  
    }  
}

만약 불변객체를 설계할 때 값을 변경하는 메서드가 필요할 수 있는데 이 경우에는 기존 객체의 값은 불변하도록 유지하고, 메서드를 통해 새로운 값을 생성해 리턴하도록 하면 된다.


불변클래스의 용도

일반적인 클래스는 대부분 값을 변경할 수 있도록 가변 클래스로 만들어진다.
회원 클래스의 같은 경우에도 값을 변경할 수 있도록 가변클래스로 설계 된다.
불변 클래스는 값을 변경하면 안되는 특별한 경우에 만들어서 사용된다.
이 때 메서드의 이름은 setXXX가 아닌 withXXX로 설계한다.

불변으로 설계하는 여러 이유

  • 캐시 안정성
  • 멀티 쓰레드 안정성
  • 엔티티의 값 타입
728x90