Статьи

Java: разработка serialVersionUID класса

Ранее на этой неделе я хотел разработать serialVersionUID сериализуемого класса, чтобы я мог переопределить его метод toString, не нарушая ничего.

Я наткнулся на сообщение в блоге Фрэнка Кима, в котором предлагалось использовать инструмент serialver , поставляемый с JDK.

Я создал небольшой проект Maven, чтобы протестировать этот инструмент на очень простом классе:

1
2
3
4
5
6
import java.io.Serializable;
 
public class SerialiseMe implements Serializable
{
 
}

Если мы скомпилируем этот класс в JAR, а затем запустим инструмент serialver , мы увидим следующий вывод:

1
2
$ serialver -classpath target/serialiser-0.0.1-SNAPSHOT.jar SerialiseMe
SerialiseMe:    static final long serialVersionUID = -6060222249255158490L;

Я хотел быстро подтвердить, что могу сериализовать и десериализовать этот класс, используя это значение, поэтому я написал следующий фрагмент кода для сериализации класса (когда у него не было серийного UID версии):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
public class Serialiser
{
    public static void main( String[] args ) throws IOException, ClassNotFoundException
    {
        ByteArrayOutputStream bout = new ByteArrayOutputStream(  );
        ObjectOutputStream oout = new ObjectOutputStream( bout );
 
        Object value = new SerialiseMe();
 
        oout.writeObject( value );
        oout.close();
        byte[] bytes = bout.toByteArray();
 
        FileOutputStream fileOuputStream = new FileOutputStream("/tmp/foo.txt");
        fileOuputStream.write(bytes);
        fileOuputStream.close();
    }
}

После этого я написал следующий фрагмент кода для десериализации файла:

01
02
03
04
05
06
07
08
09
10
11
12
public class Deserialiser
{
    public static void main( String[] args ) throws IOException, ClassNotFoundException
    {
        FileInputStream fileInputStream = new FileInputStream( new File( "/tmp/foo.txt" ) );
        byte[] bytes = IOUtils.toByteArray( fileInputStream );
 
        ByteArrayInputStream in = new ByteArrayInputStream( bytes, 0, bytes.length );
        ObjectInputStream oin = new ObjectInputStream( in );
        Object object = oin.readObject();
    }
}

Я подключил серийную версию UID к классу и смог правильно десериализовать его. Я попытался изменить одну из цифр, просто чтобы убедиться, что она взорвется, и это действительно так:

1
2
3
4
5
6
import java.io.Serializable;
 
public class SerialiseMe implements Serializable
{
    static final long serialVersionUID = -6060222249255158491L;
}
01
02
03
04
05
06
07
08
09
10
11
12
13
Exception in thread "main" java.io.InvalidClassException: SerialiseMe; local class incompatible: stream classdesc serialVersionUID = -6060222249255158490, local class serialVersionUID = -6060222249255158491
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1620)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at Deserialiser.main(Deserialiser.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

serialver #ftw!

Ссылка: Java: Разработайте serialVersionUID класса у нашего партнера по JCG Марка Нидхэма в блоге Марка Нидхэма .