2009-05-22 3 views
4

나중에 변경 될 수있는 Java 객체를 직렬화해야합니다. 일부 변수를 추가하거나 제거 할 수 있습니다. 이 접근법의 구덩이 낙오와 이것이 유일한 탈출구가 남아 있다면 어떤 예방 조치를 취해야합니까?나중에 변경 될 수있는 Java 객체 직렬화

답변

9
  • 에 대한 자세한 내용을보실 수 있습니다.
  • 변경하면 일련 번호가있는 개체가 incompatible이 될 수 있습니다. 필드를 추가 및 삭제하면 클래스 버전에 필드가 존재하지 않는 인스턴스를 비 직렬화 할 때 클래스 계약 위반이 발생할 수 있습니다 (예외가 발생할 때까지 예외가 발생 함). 필드는 유형의 기본값으로 설정됩니다. 그 경우; 가장 큰 문제는 NullPointerException입니다. 이는 readObject() and writeObject()을 구현하여 피할 수 있습니다. 필드의 유형을 변경하는 등의 다른 변경으로 인해 직렬화가 완전히 실패 할 수 있습니다.
+0

필드 제거는 호환되지 않는 변경입니다. – trunkc

+1

정말입니까? 이전 버전의 클래스가 필드가없는 스트림을 읽을 때 내가 링크 된 Sun 문서에만 가능한 계약 위반이 언급됩니다. 거기에 다른 문제에 대한 언급도없고 InvalidClassException의 API 문서도 없습니다 –

+1

빠른 테스트 결과, 당신이 옳다는 것을 증명했습니다. – trunkc

1

짧은 대답은 사용자 지정 직렬화 프로세스를 구현해야한다는 것이며 변경 사항을 알고 올바른 버전으로 개체의 이전 버전을 deserialize 할 것이라고 가정합니다. 버전을 추적 할 serialVersionUID 필드도 포함시켜야하며 직렬화 된 객체가 이전 버전인지 여부를 찾는 데 도움이됩니다. 당신은 당신은 확실히 바로 처음부터 serialVersionUID 필드를 추가하기 위해 필요한이 here

0

이제 직렬화 된 개체가 변경 될 것이므로 기존의 개체를 변경하는 대신 다른 네임 스페이스를 사용하여 serialize 된 개체를 새로 만들어야합니다.

Michael과 마찬가지로 serialVersionUID를 추가하면 ToDo입니다.

2

Michael은 java.io.Serializable을 사용하여 직렬화에 대한 일부 지원을 Java가 제공함을 지적했습니다. Java 지원의 주된 문제점은 버전 관리가 복잡하고 사용자가이를 처리해야한다는 것입니다.

대신 Googles Protocol Buffers 또는 Apache Thrift를 권하고 싶습니다. 둘 다 매우 간단한 언어로 객체를 정의한 다음 직렬화 코드를 생성합니다. 둘 다 또한 모든 버전 관리를 처리하여 이전 버전이나 새 버전의 객체를 읽는 경우에 대해 걱정할 필요가 없습니다.

예를 들어 필드 막대가있는 foo() 유형이 있고 디스크에 foo 객체 묶음을 작성한 경우입니다. 그런 다음 나중에 foo에 baz 필드를 추가하고 foo 객체를 디스크에 몇 개 더 추가합니다. 그것들을 다시 읽을 때 그들은 모두 foo 객체가 될 것이고, 마치 원래의 foo 객체 모두가 단순히 baz 필드를 설정하지 않은 것처럼 보일 것입니다.

+1

표준 Java 직렬화는 serialVersionUID가 정의되어있는 경우 똑같은 작업을 수행하므로 해당 라이브러리가 제공하는 다른 기능이 필요하지 않은 경우에는 사용하지 않고 훨씬 더 많은 작업을 수행 할 수 있습니다. –