Если абстрактный класс имеет serialVersionUID

Это:

var query = from something in someList where whereClause;

является сокращением для:

var query = someList.Where(something => whereClause);

Предполагая, что someList является IEnumerable

, Where относится к Enumerable.Where Extension Метод . Этот метод ожидает Func, который вы можете определить следующим образом:

Func whereClause = address => address.Zip == 23456;
var query = someList.Where(whereClause);

62
задан Yishai 21 May 2009 в 14:37
поделиться

2 ответа

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() );
    }
}

Один раз запустите основную часть в Sub, чтобы заставить ее создать и сохранить объект. Затем измените serialVersionUID в базовом классе, закомментируйте строки в main, которые сохраняют объект (чтобы он не сохранял его снова, вы просто хотите загрузить старый), и снова запустите его. Это приведет к исключению

java.io.InvalidClassException: Base; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
46
ответ дан 24 November 2019 в 16:54
поделиться

Да, в общем, по той же причине, что и любому другому классу нужен серийный идентификатор - чтобы он не создавался для него. По сути, любой класс (не интерфейс), который реализует сериализуемый, должен определять идентификатор последовательной версии, иначе вы рискуете ошибками десериализации, когда один и тот же компилятор .class не находится в серверной и клиентской JVM.

Есть и другие варианты, если вы пытаетесь сделать что-то необычное. Я не уверен, что вы имеете в виду, говоря «это намерение подклассов ...». Собираетесь ли вы писать собственные методы сериализации (например, writeObject, readObject)? В таком случае есть и другие варианты работы с суперклассом.

см .: http://java.sun.com/javase/6/docs/api/java/io/Serializable.html

HTH Том

6
ответ дан 24 November 2019 в 16:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: