Reference/Effective-Java

    [Effective-Java] Chapter12 #90. 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라

    📌 직렬화 프록시 패턴 (Serialization Proxy Pattern) 디자인 패턴의 프록시 패턴을 응용한 것과 같다. (그래서 장/단점도 비슷하게 따라간다.) 실제 객체를 숨기고 대변인을 통해 직렬화/역직렬화를 수행한다. 📌 작성 순서 1️⃣ 프록시 클래스 생성자 private static class SerializationProxy implements Serializable { public SerializationProxy(Period p) { this.start = p.start; this.end = p.end; } } 중첩 클래스를 private static으로 선언한다. 생성자는 단 하나여야 한다. 바깥 클래스를 매개변수로 받아야 한다. 인스턴스를 복사하는 역할만 수행한다. 일관성 검사나 ..

    [Effective-Java] Chapter12 #89. 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라

    📌 Singleton 패턴과 직렬화 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public void leavingTheBuilding() {...} } 위 클래스는 외부 생성자 호출을 막음으로써, 인스턴스가 오직 하나만 만들어짐을 보장하는 싱글턴 패턴이다. 하지만 `implements Serializable`을 추가하는 순간 더 이상 싱글턴이 아니게 된다. 기본 직렬화(Item 87)을 쓰지 않고, 명시적인 readObject(Item 88)을 사용해도 소용없다. writeObject()를 제공하더라도 소용이 없다. 🤔 과연 그럴까? public class Main { publi..

    [Effective-Java] Chapter12 #88. readObject 메서드는 방어적으로 작성하라

    ✨ readObject 메서드를 작성하는 지침 • private여야 하는 객체 참조 필드는 각 필드가 가리키는 객체를 방어적으로 복사하라. • 모든 불변식을 검사하고, 어긋나면 InvalidObjectException을 던진다. (불변식 복사 → 불변식 검사) • 역직렬화 후 그래프 전체 유효성 검사가 필요하다면 ObjectInputValidation 인터페이스를 사용하라 • readObject에서 직접적이든 간접적이든, 재정의 가능한 메서드를 호출하지 마라. (초기화 되기 전에 호출된다.) 🛡️ 역직렬화 방어적 수행 🟡 As-is public final class Period implements Serializable { private final Date start; private final Date ..

    [Effective-Java] Chapter12 #87. 커스텀 직렬화 형태를 고려해보라

    📌 기본 직렬화가 괜찮은 경우 1️⃣ 직접 설계하더라도 기본 직렬화 형태와 거의 같은 결과가 나올 경우 어떤 객체의 기본 직렬화 형태는 해당 객체를 root로 하는 객체 그래프의 물리적 모습을 나름 효율적으로 인코딩한다. 객체가 포함한 데이터, 접근 가능한 모든 객체, 객체들이 연결된 위상(topology)까지 기술한다. 그러나, 이상적인 직렬화 형태는 물리적 모습과 독립된 논리적 모습만을 표현해야 한다. (공간 문제) 2️⃣ 객체의 물리적 표현과 논리적 내용이 같은 경우 public class Name implements Serializable { /** * 성. null이 아니어야 함. * @serial */ private final Stirng lastName; /** * 이름. null이 아니어야..