Если мой класс реализует Serializable, нужно ли мне реализовывать его в его подклассах?

Если у меня B расширяет A... и A реализует Serializable, нужно ли мне писать «B реализует Serializable»?

Думаю нет, но хотелось бы подтверждения...

также, если я поставлю идентификатор сериализации в A... нужно ли мне также поместить его в B? должен ли быть защищен идентификатор сериализации в A (не частный)?


person ycomp    schedule 04.02.2012    source источник
comment
Не хочу показаться язвительным, но просто попробовать это займет меньше времени, чем вам потребовалось, чтобы написать этот вопрос.   -  person Jim Kiley    schedule 04.02.2012
comment
Не хочу показаться язвительным, но это был бы очень-очень маленький веб-сайт, если бы к этому совету прислушивались постоянно.   -  person Marc Bollinger    schedule 11.02.2018


Ответы (6)


Да. Подкласс не нужно явно помечать как сериализуемый.

И пометка id как protected подойдет (с точки зрения компилятора).

Но, как показывает практика, у каждого класса должен быть свой собственный serialVersionUID.

person Azodious    schedule 04.02.2012
comment
спасибо, есть идеи, как избавиться от желтого предупреждения затмения о том, что идентификатор серийной версии не объявлен? - person ycomp; 04.02.2012
comment
Более надежным способом будет определение как private static final - person Azodious; 04.02.2012
comment
Я все еще думаю, что было бы неплохо реализовать Serializable в подклассе для ясности. Точно так же, как ArrayList реализует List, а также расширяет AbstractList, который уже реализовал List. - person clankill3r; 11.08.2015
comment
Вы должны использовать модификатор private на serialVersionUID. - person Jesse Glick; 20.11.2015
comment
Просто для ясности... это serialVersionUID или serialVersionUid? У нас есть оба здесь. - person jocull; 23.10.2018

Вам не нужно явно отмечать производное как Serializable, оно будет унаследовано. Однако serialVersionUID от родителя, хотя и унаследован, не будет использоваться в процессе сериализации. Если вы не добавите serialVersionUID к дочернему, он будет сгенерирован.

Смотри ниже:

public class A implements Serializable {
    protected static final long serialVersionUID = 1L;
}

public class B extends A {
}

public class Main {

    public static void main(String[] args){

        A a = new A();
        B b = new B();

        Class aClass = a.getClass();
        Class bClass = b.getClass();

        long aUid = ObjectStreamClass.lookup(aClass).getSerialVersionUID();
        long bUid = ObjectStreamClass.lookup(bClass).getSerialVersionUID();

        System.out.printf("serialVersionUID:\n");
        System.out.printf("b inherited from a: %d\n", b.serialVersionUID);
        System.out.printf("a used by serialization: %d\n",aUid);
        System.out.printf("b used by serialization: %d\n",bUid);
    }

}

Выход:

серийная версияUID:

б унаследовано от а: 1

a используется сериализацией: 1

b используется сериализацией: -3675232183873847366

person Howard Swope    schedule 23.07.2015

В моем согласии с ответом @azodious дочерний класс наследует сериализуемые свойства родительского класса, но вам придется явно объявить serialVersionUID.

Из документации по Java: https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

Также настоятельно рекомендуется, чтобы в явных объявлениях serialVersionUID по возможности использовался модификатор private, поскольку такие объявления применяются только к непосредственно объявляющему классу — поля serialVersionUID не используются в качестве унаследованных членов.

person vsingh    schedule 13.12.2013

Пометки id как защищенной будет достаточно с точки зрения компилятора. Однако теоретически смысл поля serialVersionUID в классе Serializable состоит в том, чтобы легко различать «версии» класса при его десериализации — четко обозначать, когда данный объект может быть десериализован в экземпляр предоставленного класса (если serialVersionUID разные, выбрасывается исключение). Если вы хотите четко отслеживать версии и природу объекта, объявите serialVersionUID для каждого подкласса.

person Jim Kiley    schedule 04.02.2012
comment
Я думаю, что serialVersionUIDs объявлен для JVM, чтобы идентифицировать изменение класса. и JVM может получить его из базового класса, поэтому это не должно иметь никакого значения. - person Azodious; 04.02.2012
comment
Ну да, но я действительно хотел сказать, что не относитесь к serialVersionUID как к раздражающему фактору, от которого вы пытаетесь избавиться. Узнайте, почему это происходит, и относитесь к этому соответствующим образом. - person Jim Kiley; 04.02.2012
comment
Да, но у нас может быть два разных класса с одним и тем же serialVersionUID. если это был простой класс без явного расширения какого-либо класса, то он должен быть обязательным. - person Azodious; 04.02.2012
comment
я думал, что старые файлы не будут совместимы, если я попытаюсь загрузить их с новыми модифицированными классами... поэтому вместо этого я никогда не буду менять классы... (это относительно простые классы... у меня просто есть список из них я сериализую)... так что на всякий случай я поместил кучу строковых и целых и логических полей и назвал их зарезервированными1,2 и т.д. .. в маловероятном случае мне нужно будет прикрепить больше данных к классу в будущем... но файл все равно будет в том же формате - person ycomp; 04.02.2012

Нет, потому что B уже реализует его через свой базовый класс A. Вот что такое наследование.

person Lucius    schedule 04.02.2012

Объект Java является сериализуемым, если его класс или любой из его суперклассов реализует либо интерфейс java.io.Serializable, либо его субинтерфейс, java.io.Externalizable.

Вы можете взглянуть на официальную документацию и найти это там: https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html

person minotna    schedule 23.02.2017