Item 89 : 인스턴스 수를 통제해야 한다면 readResolve 보다는 열거 타입을 사용하라
2021. 9. 26. 08:46
// 아이템 3에서 만들었던 싱글톤 패턴
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}
- 이 클래스 선언에 implements Serializable을 추가하는 순간 더 이상 싱글턴이 아니게 된다.
- 어떤 readObject를 사용하든 이 클래스가 초기화될 때 만들어진 인스턴스와는 별개인 인스턴스를 반환하게 된다.
readResolve 기능을 이용하면 readObject가 만들어낸 인스턴스를 다른 것으로 대체할 수 있다.
- 역직렬화한 객체의 클래스가readResolve 메소드를 적절히 정의해뒀다면, 역직렬화 후 새로 생성된 객체를 인수로 이 메소드가 호출되고, 이 메소드가 반환한 객체 참조가 새로 생성된 객체를 대신해 반환된다.
- readResolve 메소드를 추가해 싱글톤 속성을 유지할 수 있다.
// 인스턴스 통제를 위한 readResolve
private Object readResolve() {
// 진짜 Elvis를 반환하고 가짜 Elvis는 가비지 컬렉터에 맡긴다.
return INSTANCE;
}
- 이 메소드는 역직렬화한 객체는 무시한다.
- 따라서 Elvis는 transient로 선언해야 한다.
- 사실 readResolve를 인스턴스 통제 목적으로 상요한다면 객체 참조 타입 인스턴스 필드는 모두 transient로 선언해야 한다.
// 잘못된 싱글턴 - transient가 아닌 참조필드를 가지고 있다.
public class Elvis implements serializable {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {}
private String[] favoriteSongs =
{"Hound Dog", "Heartbreak Hotel"};
public void printFavoirtes() {
System.out.println(Arrays.toString(favoriteSongs));
}
private Obejct readResolve() {
return INSTANCE;
}
}
// 객체 참조를 훔치는 도둑 클래스
public class ElvisStealer implments Serializable {
static Elvis impersonator;
private Elvis payload;
private Object readResolve() {
// resolve 되기 전의 Elvis 인스턴스의 참조를 저장
impersonator = payload;
// favoriteSongs 필드에 맞는 타입의 객체를 반환
return new String[] {"A Fool Such as I"};
}
private static final long serialVersionUID = 0;
}
직렬화 가능한 인스턴스 통제 클래스를 열거타입을 통해 구현
- 선언한 상수 외의 다른 객체는 존재하지 않음을 자바가 보장해줌
// 열거 타입 싱글톤 - 전통적인 싱글톤보다 우수하다.
public enum Elvis {
INSTANCE;
private String[] favoriteSongs =
{"Hound Dog", "Heartbreak Hotel"};
public void printFavoirtes() {
System.out.println(Arrays.toString(favoritSongs));
}
}
'책 > 이펙티브자바' 카테고리의 다른 글
이펙티브 자바 리뷰 (1회독을 마치며) (0) | 2021.09.28 |
---|---|
Item 90 : 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라 (0) | 2021.09.27 |
Item 88 : readObject 메소드는 방어적으로 작성하라 (0) | 2021.09.25 |
Item 87 : 커스텀 직렬화 형태를 고려해보라 (0) | 2021.09.24 |
Item 86 : Serializable을 구현할지는 신중히 결정하라 (0) | 2021.09.23 |