В чем разница между сериализацией и простым хранением объекта на диске?


Меня это смущает. Так как при реализации Сериализуемого класса мы должны использовать такие классы, как FileOutputStream, ObjectOutputStream или что-то в этом роде. Тогда почему бы нам просто не использовать эти классы, чтобы делать такие вещи, как вывод объекта в файл и ввод объекта из файла для поддержания статуса объекта напрямую? Почему мы должны сначала реализовать сериализуемый, а затем сделать то же самое?

4 2

4 ответа:

Поймите это так...

Serializable-это маркерный интерфейс, который обозначает, что объект вашего класса может быть преобразован в поток байтов и в конечном итоге обратно в объект java, если это необходимо. Изначально вы можете подумать, что каждый класс должен быть сериализуемым, но это неверно.]}

входные и выходные потоки, которые имеют некоторый дескриптор файла для чтения. Этот дескриптор файла закрывается, когда поток становится недоступным. Поэтому сериализация в данном случае не производит смысл; и де-сериализация никогда не восстановит этот дескриптор.

Таким образом, это должно ответить, почему требуется маркировка как Сериализуемая?

Теперь реализуем методы, которые определяют, как ваш объект должен быть записан или прочитан; это должно быть определено вами, и поэтому вам нужны все эти объекты потока и методы readObject, writeObject. Надеюсь, это даст вам немного больше понимания этой концепции.

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

Сама сериализация - это преобразование объекта в нечто, что может быть сохранено или передано, то есть в виде потока байтов. Вы можете сравнить сериализацию с замораживанием, методом, используемым для изготовления Нескафе - вся вода удаляется и только кофейная эссенция хранится в банке - только состояние объекта (значения полей) преобразуется в байт-поток, а не его методы.

Как уже говорилось в fvu, сериализация - это процесс преобразования экземпляра класса в массив байтов и заместителей. Не каждый класс в Java может быть преобразован в массив байтов (подумайте о классе Thread, просто нет смысла преобразовывать поток в массив байтов), и именно поэтому вам (и нам) нужно реализовать Serializable в тех объектах, которые могут быть преобразованы.

Serializable это просто интерфейс маркера, он не требует каких-либо методы, которые будут реализованы. В большинстве случаев этого достаточно: просто сделайте ваш сериализуемый объект реализовать интерфейс, а затем использовать поведение по умолчанию.

Что поведение сериализации по умолчанию реализуется в классах ObjectInputStream и ObjectOutputStream. FileInputStream и FileOutputStream - это различные классы, предназначенные для чтения и записи данных из файлов на диске.

Если вы хотите записать объект на диск, вам нужно использовать что-то вроде этого:

MyObject obj = ... // your object instance
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("/path/to/file"));
stream.writeObject(obj);

Чтобы прочитать объект назад, вам нужно это:

ObjectInputStream stream = new ObjectInputStream(new FileInputStream("/path/to/file"));
MyObject obj = (MyObject) stream.readObject();

Но иногда вы захотите сериализовать/десериализовать экземпляр объекта в память, а не на диск, тогда вы будете использовать что-то вроде этого:

MyObject obj = ... // your object instance
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
byte[] data = baos.toByteArray();
Я опущу часть чтения объекта обратно из массива байтов, поскольку это довольно просто, но думаю, что в огромных комбинациях, которые вы можете использовать, будут все различные потоки ввода / вывода, предоставляемые JVM.
В приведенных выше примерах используется поведение сериализации по умолчанию. Однако вы можете столкнуться со сценариями в котором данный класс, который вы хотите сериализовать, содержит ссылки на другие экземпляры класса, которые не реализуют интерфейс Serializable. Нам нужно пометить эти ссылки модификатором transient, чтобы поведение сериализации по умолчанию игнорировало их, и нам нужно переопределить поведение по умолчанию, предоставляя частные методы readObject и writeObject, которые будут вызваны при попытке сериализовать/десериализовать экземпляр объекта.

Кроме того, некоторые классы могут предоставьте замещающий объект (экземпляр объекта другого сериализуемого класса), когда происходит сериализация. Этот замещающий объект будет содержать состояние исходного класса таким образом, чтобы этот исходный класс можно было восстановить из этого замещающего объекта. Это поведение реализуется с помощью метода writeReplace в исходном классе и метода readReplace в классе замены. Обратите внимание, что как исходный, так и замещающий классы должны реализовывать интерфейс Serializable, но только данные в замене объект будет сериализован .

И последнее, но не менее важное: существует возможность полностью переопределить протокол сериализации по умолчанию, реализующий Externalizable интерфейс. Это не маркерный интерфейс, как Serializable , и вы должны реализовать методы преобразования состояния вашего объекта в массив и наоборот. Вы все еще будете пользоваться ObjectInputStream/ObjectOutputStream пара для сериализации (externalize ??) externalizable экземпляры объектов, но теперь логика, чтобы преобразование класса в массив байтов-это уже не то, что предоставляет JVM, а то, что вы написали в своем классе при реализации класса Externalizable.

Вся эта информация содержится в ссылке , которую thinksteep предоставил в качестве комментария.

Сериализация-это процесс взятия объекта и записи его в байтовый массив (позднее чтение из байтового массива в объект)

ObjectOutputStream использует сериализацию внутри, он превращает объект в байт [] с помощью serialize и записывает его на свой выход