Item86. Serializable 구현할지는 신중히 결정하라
어떤 클래스의 객체를 직렬화 할 수 있게 하려면 클래스 선언에 implments Serializable만 덧붙이면 된다.
Serializable을 구현하면 release한뒤에는 수정하기 어렵다. 클래스가 Serializable을 구현하면 직렬화된 byte stream 인코딩도 하나의 공개 API가 된다. (직렬화한 형태도 계속 지원해야 한다.)
또한 custom 직렬화 형태를 설계하지않고, default로 두게 되면 private와 package-private 필드마저도 공개가 된다. 따라서 직렬화를 한다고 하면 직렬화 형태도 주의해서 설계해야 한다고 한다.
직렬화의 단점
- stream 고유 식별자 (직렬 버전 UID) : 모든 직렬화된 class는 고유 식별 번호를 부여받는다.
seraialVersionUID라는 이름의 static final long 필드로 이 번호를 명시하지 않으면 시스템이 runtime에 암호 해시 함수(SHA-1)을 생성해 자동으로 클래스안에 넣는다. 이떄 클래스 멤버들이 고려되서 생성되기 떄문에 클래스가 수정되면 이 UID값도 같이 수정된다.
버그와 보안 구멍이 생길 위험이 높아진다. 역직렬화는 숨은 생성자를 통해 객체를 만들며, 클래스 불변식 꺠짐과 허가되지 않은 접근에 쉽게 노출된다는 단점을 가지고 있다.
해당 class의 신버전을 release할때 테스트할점이 늘어난다.
직렬화 가능한 class가 수정되면 신버전 class도 구버전 직렬화 형태로 역직렬화 되는지, 직렬화 되는지 모두 테스트해보아야 한다. 따라서 매 release 횟수에 비례하여 테스트양이 증가한다.
일반적인 사용 사례
- BigInteger,Instant와 같은 값 타입 클래스와 Collection 클래스들은 Serializable을 구현하고, Thread Pool 처럼 동작하는 객체를 표현하는 클래스들은 대부분 Serializable을 구현하지 않는다고 한다.