Java: эффективность writeObject vs writeExternal
В нем говорилось, что механизм сериализации Java по умолчанию не очень эффективен, потому что: a) он обнаруживает, какие поля записывать/читать через отражение, которое обычно медленное; b) он записывает дополнительные данные в поток.
Один из способов сделать его более эффективным - реализовать Externalizable и его методы writeExternal/readExternal.
Здесь вопрос: если я вместо этого предоставляю методы writeObject/readObject и не вызываю в них deafiltWriteObject/defaultReadObject, тогда этот механизм не будет использовать отражение, чтобы выяснить, какие поля писать/читать, а также выиграть ' t записать дополнительные данные в поток (или это будет неточно). Итак, с точки зрения эффективности, реализует writeObject/readObject, упомянутый выше, как при реализации Externalizable? Или последний вариант дает некоторые практические преимущества, которые первый не делает?
EDIT: различие, конечно, заключается в том, что класс Serializable, реализующий readObject/writeObject, подклассифицирован, и если подкласс имеет свой собственный объект readObject/writeObject, им не нужно вызывать super readObject/writeObject. Не так, если супер/подкласс вместо этого реализует Externalizable. В этом случае необходимо явно вызвать функцию super writeExternal/readExternal. Однако это различие не имеет значения с точки зрения эффективности.
Ответы
Ответ 1
В процессе выбора класса /writeObject/readObject еще есть над головой. но значительно сокращается.
Это может работать так же, как и Externalizable, в зависимости от того, что вы делаете, и используете ли вы дополнительные параметры, которые он вам дает. например readObject предполагает, что вы каждый раз создаете новый объект, Externalizable имеет readResolve, что означает, что вы можете повторно использовать объекты.
http://docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/input.html
Во многих случаях объекты утилизации являются "следующим" шагом в ускорении десериализации. (Предполагая, что для вас вариант)
http://vanillajava.blogspot.co.uk/2011/10/recycling-objects-to-improve.html
Ответ 2
Основное отличие в дизайне классов заключается в том, что Serializable
будет работать над любым классом, тогда как Externalizable
работает только с изменяемыми классами с общедоступными конструкторами по умолчанию (no-arg).
Ответ 3
Нашел пару вещей, экспериментируя и просматривая код механизма сериализации:
1), если объект обнаружен как Externalizable, он переключается на Externalizable, и на него вызывается соответствующий метод; тогда как для объекта Serializable он рефлексивно проверял, имеет ли он readObject/writeObject. Так что, возможно, это немного замедляется,
2) объем данных, написанных для Externalizable, немного меньше, чем Serializable с readObject/writeObject (я обнаружил разницу в 1 байт для следующего кода, когда я написал объект B).
Для Externalizable:
static class A implements Externalizable
{
@Override
public void writeExternal(ObjectOutput out) throws IOException
{
System.out.println("A write called");
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
System.out.println("A read called");
}
}
static class B extends A implements Externalizable
{
@Override
public void writeExternal(ObjectOutput out) throws IOException
{
super.writeExternal(out);
System.out.println("B write called");
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
super.readExternal(in);
System.out.println("B read called");
}
}
Для Serializable:
static class A implements Serializable
{
private void writeObject(ObjectOutputStream out) throws IOException
{
System.out.println("A write called");
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
System.out.println("A read called");
}
}
static class B extends A implements Serializable
{
private void writeObject(ObjectOutputStream out) throws IOException
{
System.out.println("B write called");
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
System.out.println("B read called");
}
}