문제

Java에서 클래스가 직렬화 가능하지만 추상적 인 경우 SerialversionUid가 오래 선언되었거나 서브 클래스에만 요구되는 경우?

이 경우 실제로 모든 서브 클래스가 유형의 목적이 RMI 호출에 사용되므로 직렬화를 처리한다는 의도입니다.

도움이 되었습니까?

해결책

SerialversionUid는 탈취 된 객체와 클래스의 현재 버전 간의 호환성을 결정하기 위해 제공됩니다. 따라서 첫 번째 버전의 클래스 또는이 경우 추상 기본 클래스에서는 실제로 필요하지 않습니다. 해당 추상 클래스의 인스턴스가 없을 것입니다. 직렬화/사형화 할 수 있으므로 SerialVersionUid가 필요하지 않습니다.

(물론, 그것은 컴파일러 경고를 생성하고, 제거하고 싶은가?)

제임스의 의견이 맞다는 것이 밝혀졌습니다. 추상적 인 기본 클래스의 SerialversionUid 하다 서브 클래스로 전파됩니다. 그것에 비추어, 당신 하다 기본 클래스에서 SerialversionUid가 필요합니다.

테스트 할 코드 :

import java.io.Serializable;

public abstract class Base implements Serializable {

    private int x = 0;
    private int y = 0;

    private static final long serialVersionUID = 1L;

    public String toString()
    {
        return "Base X: " + x + ", Base Y: " + y;
    }
}



import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Sub extends Base {

    private int z = 0;

    private static final long serialVersionUID = 1000L;

    public String toString()
    {
        return super.toString() + ", Sub Z: " + z;
    }

    public static void main(String[] args)
    {
        Sub s1 = new Sub();
        System.out.println( s1.toString() );

        // Serialize the object and save it to a file
        try {
            FileOutputStream fout = new FileOutputStream("object.dat");
            ObjectOutputStream oos = new ObjectOutputStream(fout);
            oos.writeObject( s1 );
            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        Sub s2 = null;
        // Load the file and deserialize the object
        try {
            FileInputStream fin = new FileInputStream("object.dat");
            ObjectInputStream ois = new ObjectInputStream(fin);
            s2 = (Sub) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println( s2.toString() );
    }
}

하위에서 메인을 한 번 실행하여 객체를 만들고 저장하도록하십시오. 그런 다음 기본 클래스에서 SerialversionUid를 변경하고 메인의 선을 주석으로 댓글을 달아 객체를 저장하지 않으므로 다시 저장하지 않고 이전 제품을로드하려고합니다). 이로 인해 예외가 발생합니다

java.io.InvalidClassException: Base; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

다른 팁

그렇습니다. 일반적으로 다른 클래스에는 일련의 ID가 필요합니다. 기본적으로 직렬화 가능한 것을 구현하는 모든 클래스 (인터페이스가 아님)는 일련 버전 ID를 정의하거나 동일한 .class 컴파일이 서버 및 클라이언트 JVM에 있지 않은 경우 해제 오류를 위험에 빠뜨려 야합니다.

멋진 일을하려는 경우 다른 옵션이 있습니다. "하위 클래스의 의도입니다 ..."라는 의미가 확실하지 않습니다. 사용자 정의 직렬화 방법 (예 : WriteObject, readObject)을 작성 하시겠습니까? 그렇다면 슈퍼 클래스를 다루는 다른 옵션이 있습니다.

보다:http://java.sun.com/javase/6/docs/api/java/io/serializable.html

HTH TOM

실제로, 누락 된 경우 Tom의 링크를 가리키는 serialVersionID 실제로 직렬화 런타임에 의해 계산됩니다. 즉, 컴파일 중에는 그렇지 않습니다.

직렬화 가능한 클래스가 SerialversionUid를 명시 적으로 선언하지 않으면 Serialization 런타임은 클래스의 다양한 측면을 기반으로 해당 클래스의 기본 SerialversionUid 값을 계산합니다 ...

이것은 다른 버전의 JRE를 갖는 것을 더욱 복잡하게 만듭니다.

개념적으로 직렬화 된 데이터는 다음과 같습니다.

subClassData(className + version + fieldNames + fieldValues)
parentClassData(className + version + fieldNames + fieldValues)
... (up to the first parent, that implements Serializable)

따라서 사형화되면 계층 구조의 모든 클래스에서 버전의 불일치로 인해 사막화가 실패합니다. 인터페이스에 저장된 것은 없으므로 버전을 지정할 필요가 없습니다.

대답: 예, 제공해야합니다 serialVersionUID 기본 추상 클래스에서도. 필드가 없더라도className + version 필드가 없어도 저장됩니다).

또한 다음 사항에 유의하십시오.

  1. 클래스에 필드가 없으면 직렬화 된 데이터 (제거 된 필드)에서 발견되는 필드가 없으면 무시됩니다.
  2. 클래스에 필드가있는 경우 직렬화 된 데이터 (새 필드)에 존재하지 않는 경우 0/false/null로 설정됩니다 (예상대로 기본값이 아닌).
  3. 필드가 데이터 유형을 변경하면 사형화 된 값을 새 유형에 할당 할 수 있어야합니다. 예, 당신이 있었다면 Object 현장 String 값, 필드 유형 변경 String 성공하지만 변화 Integer 습관. 그러나 분야의 변화 int 에게 long 할당 할 수는 있지만 작동하지 않습니다 int 가치 long 변하기 쉬운.
  4. 서브 클래스가 더 이상 직렬화 된 데이터로 확장되는 상위 클래스를 확장하지 않으면 (사례 1에서와 같이) 무시됩니다.
  5. 서브 클래스가 이제 클래스를 확장하는 경우 직렬화 된 데이터에서 찾을 수없는 클래스를 확장하면 부모 클래스 필드는 0/false/null 값으로 복원됩니다 (사례 2에서와 같이).

간단한 말로 : 필드를 재정렬하고 추가 및 제거하고 클래스 계층 구조를 변경할 수도 있습니다. 필드 나 클래스의 이름을 바꾸지 않아야합니다 (실패하지는 않지만 값은 필수화되지 않습니다). 원시 유형으로 필드 유형을 변경할 수 없으며 모든 값에서 새 유형을 할당 할 수있는 경우 참조 유형 필드를 변경할 수 있습니다.

참고 : 기본 클래스가 직렬화가 가능하지 않고 서브 클래스 만 수행하는 경우 기본 클래스의 필드는 다음과 같이 작동합니다. transient.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top