객체 입출력

Ajisai·2023년 7월 26일
0

Java

목록 보기
16/17

Serialization

  • Serializable 인터페이스를 구현하면 직렬화 가능 클래스가 된다.
  • Serializable 인터페이스는 아무것도 없는 빈 인터페이스다. 그냥 직렬화할 거라고 표시하기 위해 implement하는 것.
  • 필드만 직렬화에 포함된다.
  • static, transient 필드는 직렬화에서 제외된다.
  • 역직렬화 시 객체의 hash code는 달라진다.
    - hashCode 정의에 따라 같을 수도 있다.

serialVersionUID

  • serialization 시의 UID와 deserialzation 시의 UID는 같아야 한다.
  • 같은 클래스임을 식별하는 식별자 역할을 한다.
  • Serializable 인터페이스의 구현 객체를 컴파일 하면 자동으로 정적 필드 serialVersionUID가 추가된다.
  • 때문에 직렬화된 객체를 네트워크로 전송하는 경우 한 쪽에서 클래스 변경 후 재컴파일하면 serialVersionUID가 달라진다.
  • 이 경우 역직렬화 시 InvalidClassException이 발생한다.
  • 그래서 명시적으로 선언하는 게 좋다.
public class XXX implements Serializable {
   static final long serialVersionUID = LONG_VALUE;
}
  • 임의로 줄 수 있는데 가능하면 클래스마다 다르게 하는 게 좋다.
  • {{JDK 설치 경로}}/bin/serialver.exe는 자동으로 serialVersionUID를 생성한다.
  • 결과적으로 저쪽 heap에 있는 데이터를 가져와서 이쪽 heap에서 쓰는 것처럼 된다.

상속

  • super class가 Serializable을 구현하고 있다면 super class 직렬화 시 sub class도 직렬화된다.
    이는 sub class의 Serializable 구현 여부와 무관하다.
  • sub class만 Serializable을 구현하고 있다면 super class는 직렬화되지 않는다.

이에 대한 방법은 다음의 두 가지가 있다.
1. super class가 Serializable을 구현한다.
2. sub class에서 writeObject()readObject()를 선언해 직접 super class의 field를 출력한다.

private void writeObejct(ObjectOutputStream out) throws IOExceptino {
    out.writeXXX(SUPER_CLASS_FIELD); // write fields of super object

    ...

    out.defaultWriteObject(); //serialize fields of sub object
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    SUPER_CLASS_FIELD = in.readXXX(); // read fields of super object
    
    ...
    
    in.defaultReadObject(); // deserialize fields of sub object

}

당연히 전자의 방법이 더 좋다.

profile
Java를 하고 싶었지만 JavaScript를 하게 된 사람

0개의 댓글

관련 채용 정보