Effective Java ‐ Item 89⚠️ - dnwls16071/Backend_Summary GitHub Wiki
아이템 89 - 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라
- 싱글턴으로 구현된 클래스는 인스턴스를 하나만 만들어지는 것을 보장한다.
싱글턴을 직렬화하는 경우 문제점
- 클래스에
implements Serializable을 추가하는 순간 더 이상 싱글턴이 아니게 된다. - 기본 직렬화를 쓰지 않더라도, 그리고 명시적인 readObject를 제공하더라도 소용없다.
- 어떤 readObject를 사용하든 이 클래스가 초기화될 때 만들어진 인스턴스와는 별개인 인스턴스를 반환하게 된다.
readResolve 기능을 이용하는 경우
- readObject가 만들어낸 인스턴스를 다른 것으로 대체할 수 있다.
역직렬화한 객체의 클래스가 readResolve 메서드를 적절히 정의해뒀다면,역직렬화 후 새로 생성된 객체를 인수로 이 메서드가 호출* 이 메서드가 반환한 객체 참조가 새로 생성된 객체를 대신해 반환된다.- 대부분의 경우 이때 새로 생성된 객체의 참조는 유지하지 않으므로 바로 가비지 컬렉션 대상이 된다.
Serializable의 구현과 readResolve 메서드 제공
- 싱글턴의 속성을 유지하기 위한 방법
- readResolve()
- 역직렬화한 객체는 무시하고 클래스 초기화 때 만들어진 인스턴스를 반환
- 이때 인스턴스의 직렬화 형태는 아무런 실 데이터를 가질 이유가 없기 때문에 모든 인스턴스 필드를 transient로 선언
- readResolve()
- readResolve()를 인스턴스 통제 목적으로 사용하려는 경우
- 객체 참조 타입 인스턴스 필드는 모두 transient로 선언해야 한다.
readResolve 메서드의 접근성에 대한 이야기
- final 클래스인경우 readResolve 메서드는 private 접근 제한자 이어야 한다.
final 이 아닌 클래스의 경우 주의사항
- 접근 제한자 설정시
private으로 선언하면 하위 클래스에서 사용할 수 없다.package-private으로 선언하면 같은 패키지에 속한 하위 클래스에서만 사용할 수 있다.protected나public으로 선언하면 이를 재정의하지 않은 모든 하위 클래스에서 사용할 수 있다.protected나public이면서 하위 클래스에서 재정의 하지않았다면, 하위 클래스의 인스턴스를 역직렬화하면 상위 클래스의 인스턴스를 생성하여 ClassCastException을 일으킬 수 있다.