24 нояб. 2006 г.

java :: serialization

Расшрияя интерфейс Serializable следует не забывать использовать serialVersionUID (о котором сказано в java docs, и который следует перегенерировать каждый раз, когда меняются не transient поля класса).

Для сравнения небольшой пример:
класс A:
package package0;

import java.io.Serializable;

public class A implements Serializable{
private final String name;
private final String description;
private long ieee;

public A(final String name, final String description, long ieee) {
this.name = name;
this.description = description;
this.ieee = ieee;
}

public String getDescription() {
return this.description;
}

public long getIeee() {
return this.ieee;
}

public void setIeee(long ieee) {
this.ieee = ieee;
}

public String getName() {
return this.name;
}
}

и класс B:
package package0;

import java.util.ArrayList;
import java.util.List;

public class B extends A {
private final List<B> children;
public B(String name, String description, long ieee, final List<B> children) {
super(name, description, ieee);
this.children = new ArrayList<B>(children);
}

public List<B> getChildren() {
return this.children;
}
}

И такие же два класса в package1, но уже с проставленными serialVersionUID.

Результаты (на моей рабочей машине):
  final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);


for(int i = 0; i < count; i++){
oos.reset();
{
final List<package0.B> list = new ArrayList<package0.B>();

final List<package0.B> emptyList = Collections.emptyList();
list.add(new package0.B("name0", "0 description", 0x7f4ceeff, emptyList));
list.add(new package0.B("name1", "1 description", 0x7f3ceeff, emptyList));
list.add(new package0.B("name2", "2 description", 0x7f2ceeff, emptyList));
list.add(new package0.B("name3", "3 description", 0x7f1ceeff, emptyList));
list.add(new package0.B("name4", "4 description", 0x7f0ceeff, emptyList));

final package0.B b = new package0.B("name", "description", 0x7fcceeff, list);

long time0 = System.nanoTime();
oos.writeObject(b);
long time1 = System.nanoTime();

final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);

long time2 = System.nanoTime();
ois.readObject();
long time3 = System.nanoTime();

s0 += time3 - time2 + time1 - time0;
}
}

и такое же для классов из package1

при count = 1:
serialVersionUID time 3849mks, wo serialVersionUID time 63323mks, ratio ~16

при count = 100 (усреднённое время):
serialVersionUID time 1369mks, wo serialVersionUID time 2142mks, ratio:1.56

при count = 1000 (усреднённое время):
serialVersionUID time 690mks, wo serialVersionUID time 986mks, ratio:1.42

В спецификации нигде явно не говориться, что serialVersionUID посчитанный в run time'е где-то как-то cache'ируется, но по тестам это очевидно. Равно как и очевидно, что прописанное поле в статике всё равно быстрее.

Комментариев нет: