-
불변 객체란 뭘까?
말만 들으면 변하지않는 객체? 라는 생각이 든다.
먼저 객체는 언제 변할까?
더보기- 인스턴스 변수 직접 수정: 객체의 인스턴스 변수가 변경 가능한 타입인 경우, 해당 변수에 접근하여 값을 수정할 수 있다.
Car car = new Car(); car.speed = 100; // 속도 변경
- Setter 메서드 사용: 객체에는 메서드를 통해 내부 상태를 변경하는 기능을 제공할 수 있다. 이러한 메서드를 "Setter"라고 하는데, Setter 메서드는 객체의 특정 속성을 변경하는 데 사용된다.
public class Car { private int speed; // Setter 메서드 public void setSpeed(int newSpeed) { this.speed = newSpeed; } } // 사용예시 Car car = new Car(); car.setSpeed(100); // 속도 변경
- 다른 메서드를 통한 간접적인 값 변경: 객체의 메서드를 호출하여 내부 상태를 변경할 수도 있다. 이 경우 메서드 내부에서 내부 상태를 수정하거나 다른 로직에 따라 값을 변경함.
public class Car { private int speed; // 가속 메서드 public void accelerate(int amount) { this.speed += amount; } } // 사용예시 Car car = new Car(); car.accelerate(20); // 속도 변경
그럼 불변 객체란?
불변객체는 재할당은 가능하지만, 한번 할당하면 내부 데이터를 변경할 수 없는 객체 라고 한다.
즉, 객체에 값을 할당하면 내부 데이터를 변경시킬 수 없다는 것으로 String, Integer, Boolean 등이 있다고 한다.
먼저 장단점을 알아보자
Immutable Object의 장단점
장점
- 객체에 대한 신뢰도가 높아집니다. 객체가 한번 생성되어서 그게 변하지 않는다면 transaction 내에서 그 객체가 변하지 않기에 우리가 믿고 쓸 수 있기 때문입니다.
- 생성자, 접근메소드에 대한 방어 복사가 필요없습니다.
- 멀티스레드 환경에서 동기화 처리없이 객체를 공유할 수 있습니다.
단점
- 객체가 가지는 값마다 새로운 객체가 필요합니다. 따라서 메모리 누수와 새로운 객체를 계속 생성해야하기 때문에 성능저하를 발생시킬 수 있습니다.
그럼 불변 객체는 어떻게 만들까?
Immutable Object를 만드는 기본적인 아이디어는 필드에 final을 사용하고, Setter를 구현하지 않는 것으로
public 을 private final으로 변경하면 불변 객체로 변하게 된다.
이러면 외부에서 값을 수정할 수 없게된다.
그러나 이건 원시 타입만 가능하고 참조 타입이 있는 경우는 추가적인 작업이 필요하다.
원시타입? 참조타입?
더보기필드가 원시 타입만 있는 경우에는 해당 필드에는 직접적인 값이 저장되어 있습니다.
이는 일반적으로 숫자, 논리값, 문자열 등과 같은 기본 데이터 유형을 의미합니다.
하지만 필드에 참조 타입이 있는 경우에는 필드가 실제 값 자체를 포함하는 것이 아니라, 값이 저장된 메모리 위치를 가리키는 참조(또는 포인터)가 저장됩니다.
이러한 참조는 다른 객체나 데이터 구조에 대한 연결을 나타내며, 필드가 해당 객체나 데이터 구조를 참조하고 있다는 것을 의미합니다.
예를 들어, 자바에서 객체는 참조 타입입니다.
클래스를 기반으로 생성된 객체는 실제 데이터가 포함된 메모리 위치를 가리키는 참조를 가집니다.
따라서 다른 객체를 참조하는 필드를 가지고 있는 경우, 해당 필드는 참조 타입으로 간주됩니다.
간단한 예를 들어보겠습니다. 자바에서 다음과 같은 클래스가 있다고 가정해봅시다:
public class Person { private String name; private Address address; // ... } public class Address { private String street; private String city; // ... }
위의 Person 클래스는 name과 address라는 두 개의 필드를 가지고 있습니다.
name 필드는 String이라는 원시 타입을 갖지만, address 필드는 Address라는 참조 타입을 갖습니다.
address 필드는 Address 클래스의 객체를 참조하며, 이 객체에는 street와 city라는 두 개의 필드가 포함되어 있습니다.따라서, 필드가 원시 타입만 있는 경우에는 필드에 직접적인 값을 저장하고, 필드가 참조 타입이 있는 경우에는 해당 필드가 다른 객체나 데이터 구조를 참조합니다.
타고 들어가서 거기도 private final로 바꿔주면 되는듯 하다.