Что такое сериализация объектов?

384

Что подразумевается под «сериализацией объекта»? Можете ли вы объяснить это с некоторыми примерами?

воин
источник
2
Если вам интересен сценарий Java EE реального мира, в котором используется сериализация,
отправляйтесь

Ответы:

400

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

TarkaDaal
источник
16
это обязательно? я должен сериализовать данные перед отправкой? в какой формат он конвертируется?
Франциско Корралес Моралес
15
@FranciscoCorralesMorales - за кулисами все данные будут сериализованы перед отправкой по потоку. То, сколько вам нужно сделать, и в каком формате это будет, зависит от того, какую платформу и библиотеки вы используете.
TarkaDaal
3
@FranciscoCorralesMorales Как вы это говорите? я имею в виду, что вы говорите, что формат зависит от платформы и библиотек. Я действительно хочу знать формат.
JAVA
1
Это применимо только к объектам? Можем ли мы сериализовать переменные (объявленные без использования объектов)?
Румадо
@Rumado Только для объектов
anKotliner
395

Вы можете думать о сериализации как о процессе преобразования экземпляра объекта в последовательность байтов (которая может быть двоичной или не зависящей от реализации).

Это очень полезно, когда вы хотите передать данные одного объекта по сети, например, из одной JVM в другую.

В Java механизм сериализации встроен в платформу, но вам нужно реализовать интерфейс Serializable, чтобы сделать объект сериализуемым.

Вы также можете предотвратить сериализацию некоторых данных в вашем объекте, пометив атрибут как временный .

Наконец, вы можете переопределить механизм по умолчанию и предоставить свой собственный; это может быть подходящим в некоторых особых случаях. Для этого вы используете одну из скрытых функций в Java .

Важно отметить, что сериализуемым является «значение» объекта или содержимого, а не определение класса. Таким образом, методы не сериализуются.

Вот очень простой пример с комментариями для облегчения его чтения:

import java.io.*;
import java.util.*;

// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {

    // These attributes conform the "value" of the object.

    // These two will be serialized;
    private String aString = "The value of that string";
    private int    someInteger = 0;

    // But this won't since it is marked as transient.
    private transient List<File> unInterestingLongLongList;

    // Main method to test.
    public static void main( String [] args ) throws IOException  { 

        // Create a sample object, that contains the default values.
        SerializationSample instance = new SerializationSample();

        // The "ObjectOutputStream" class has the default 
        // definition to serialize an object.
        ObjectOutputStream oos = new ObjectOutputStream( 
                               // By using "FileOutputStream" we will 
                               // Write it to a File in the file system
                               // It could have been a Socket to another 
                               // machine, a database, an in memory array, etc.
                               new FileOutputStream(new File("o.ser")));

        // do the magic  
        oos.writeObject( instance );
        // close the writing.
        oos.close();
    }
}

Когда мы запускаем эту программу, создается файл «o.ser», и мы видим, что произошло позади.

Если мы изменим значение: someInteger , например, Integer.MAX_VALUE , мы можем сравнить вывод, чтобы увидеть, в чем разница.

Вот скриншот, показывающий именно эту разницу:

альтернативный текст

Можете ли вы определить различия? ;)

В сериализации Java есть еще одно релевантное поле: serialversionUID, но, думаю, это уже слишком долго, чтобы его охватить.

OscarRyz
источник
1
@ raam86 экземпляр является объектом сериализации. Вы можете думать в основном методе как отдельная программа, которая создает объект типаSerializationSample
OscarRyz
2
@ raam86 является первым оператором в методе main: SerializationSample instance = new SerializationSample();затем создается выход, и объект записывается в этот вывод.
OscarRyz
1
Ой. Не достаточно близко. Большой!!
raam86
1
@jacktrades Почему бы тебе не попробовать? Просто скопируйте / вставьте пример и посмотрите, как генерируется NotSerializableException :)
OscarRyz
1
@jacktrades, потому что компьютеру не сказали, что объекту разрешено сериализоваться :) что означает oos?
Крис Беннетт
101

Смею ответить на 6-летний вопрос, добавив только очень высокого уровня понимания для людей, плохо знакомых с Java

Что такое сериализация?

Преобразование объекта в байты

Что такое десериализация?

Преобразование байтов обратно в объект (десериализация).

Когда используется сериализация?

Когда мы хотим сохранить объект. Когда мы хотим, чтобы объект существовал после жизненного цикла JVM.

Пример из реального мира:

Банкомат. Когда владелец счета пытается вывести деньги с сервера через банкомат, информация о владельце счета, такая как информация о снятии, будет сериализована и отправлена ​​на сервер, где данные будут десериализованы и использованы для выполнения операций.

Как сериализация выполняется в Java.

  1. Воплощать в жизнь java.io.Serializable интерфейс (маркерный интерфейс, поэтому нет способа реализовать).

  2. Сохранять объект: использовать java.io.ObjectOutputStream класс, поток фильтра, который является оберткой вокруг потока байтов более низкого уровня (чтобы записать объект в файловые системы или передать плоский объект по сетевому проводу и перестроить на другой стороне).

    • writeObject(<<instance>>) - написать объект
    • readObject() - прочитать сериализованный объект

Помните:

Когда вы сериализуете объект, будет сохранено только состояние объекта, а не файл класса объекта или методы.

Когда вы сериализовали 2-байтовый объект, вы видите 51-байтовый сериализованный файл.

Действия по сериализации и десериализации объекта.

Ответ для: Как он преобразовал файл в 51 байт?

  • Сначала записываются магические данные потока сериализации (STREAM_MAGIC = "AC ED" и STREAM_VERSION = версия JVM).
  • Затем он записывает метаданные класса, связанного с экземпляром (длина класса, имя класса, serialVersionUID).
  • Затем он рекурсивно записывает метаданные суперкласса, пока не найдет java.lang.Object .
  • Затем начинается с фактических данных, связанных с экземпляром.
  • Наконец, записывает данные объектов, связанных с экземпляром, начиная с метаданных, до фактического содержимого.

Если вы заинтересованы в более подробной информации о сериализации Java, перейдите по этой ссылке .

Изменить : еще одна хорошая ссылка для чтения.

Это ответит на несколько частых вопросов:

  1. Как не сериализовать ни одно поле в классе.
    Ответ: используйте временное ключевое слово

  2. Когда дочерний класс сериализуется, родительский класс сериализуется?
    Ответ: Нет, если родительский объект не расширяет поле родителей интерфейса Serializable, сериализация не выполняется.

  3. При сериализации родительского класса сериализуется ли дочерний класс?
    Ответ: Да, по умолчанию дочерний класс также сериализуется.

  4. Как предотвратить сериализацию дочернего класса?
    Ответ: а. Переопределите метод writeObject, readObject и throw NotSerializableException.

    б. также вы можете отметить все переходные поля в дочернем классе.

  5. Некоторые классы системного уровня, такие как Thread, OutputStream, его подклассы и Socket, не сериализуемы.
VdeX
источник
3
Большое спасибо за этот краткий ответ, это было очень полезно!
Ноби
21

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

Кент Бугаарт
источник
14

Мне понравилось, как @OscarRyz представляет. Хотя здесь я продолжаю историю сериализации которая была изначально написана @amitgupta.

Даже зная о структуре классов роботов и имея сериализованные данные, ученые Земли не смогли десериализовать данные, которые могут заставить роботов работать.

Exception in thread "main" java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:

Ученые Марса ждали полной оплаты. Как только оплата была произведена, ученые Марса поделились серийной версией UID с учеными Земли. Ученый Земли установил класс роботов, и все стало хорошо.

noquery
источник
9

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

Обратите внимание, что свойства объекта будут только сохранены. Если вы хотите воскресить объект снова, у вас должен быть файл класса, потому что будут храниться только переменные-члены, а не функции-члены.

например:

ObjectInputStream oos = new ObjectInputStream(                                 
                                 new FileInputStream(  new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();

Searializable - интерфейс маркера, который отмечает, что ваш класс сериализуем. Маркерный интерфейс означает, что это просто пустой интерфейс, и использование этого интерфейса уведомит JVM о том, что этот класс можно сделать сериализуемым.

Sathesh
источник
9

Мои два цента из моего собственного блога:

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

Сериализация:

Сериализация - это процесс сохранения состояния объекта. Он представлен и хранится в виде последовательности байтов. Это может быть сохранено в файле. Процесс чтения состояния объекта из файла и его восстановления называется десериализацией.

Зачем нужна сериализация?

В современной архитектуре всегда необходимо сохранять состояние объекта, а затем извлекать его. Например, в Hibernate, чтобы сохранить объект, мы должны сделать класс Serializable. Что он делает, так это то, что после сохранения состояния объекта в виде байтов его можно перенести в другую систему, которая затем может прочитать из состояния и извлечь класс. Состояние объекта может поступать из базы данных, другого jvm или отдельного компонента. С помощью сериализации мы можем получить состояние объекта.

Пример кода и объяснение:

Сначала давайте посмотрим на класс предметов:

public class Item implements Serializable{

    /**
    *  This is the Serializable class
    */
    private static final long serialVersionUID = 475918891428093041L;
    private Long itemId;
    private String itemName;
    private transient Double itemCostPrice;
    public Item(Long itemId, String itemName, Double itemCostPrice) {
        super();
        this.itemId = itemId;
        this.itemName = itemName;
        this.itemCostPrice = itemCostPrice;
      }

      public Long getItemId() {
          return itemId;
      }

     @Override
      public String toString() {
          return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
       }


       public void setItemId(Long itemId) {
           this.itemId = itemId;
       }

       public String getItemName() {
           return itemName;
       }
       public void setItemName(String itemName) {
            this.itemName = itemName;
        }

       public Double getItemCostPrice() {
            return itemCostPrice;
        }

        public void setItemCostPrice(Double itemCostPrice) {
             this.itemCostPrice = itemCostPrice;
        }
}

В приведенном выше коде видно, что класс Item реализует Serializable .

Это интерфейс, который позволяет классу быть сериализуемым.

Теперь мы видим, что переменная с именем serialVersionUID инициализируется переменной Long. Это число вычисляется компилятором на основе состояния класса и атрибутов класса. Это число, которое поможет jvm идентифицировать состояние объекта, когда он читает состояние объекта из файла.

Для этого мы можем взглянуть на официальную документацию Oracle:

Среда выполнения сериализации связывает с каждым сериализуемым классом номер версии, называемый serialVersionUID, который используется во время десериализации для проверки того, что отправитель и получатель сериализованного объекта загрузили классы для этого объекта, которые совместимы в отношении сериализации. Если получатель загрузил класс для объекта, который имеет serialVersionUID, отличный от класса соответствующего отправителя, то десериализация приведет к исключению InvalidClassException. Сериализуемый класс может объявить свой собственный serialVersionUID в явном виде, объявив поле с именем «serialVersionUID», которое должно быть статическим, конечным и типа long: ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; Если сериализуемый класс явно не объявляет serialVersionUID, затем среда выполнения сериализации вычислит значение serialVersionUID по умолчанию для этого класса на основе различных аспектов класса, как описано в Спецификации сериализации объектов Java (TM). Однако настоятельно рекомендуется, чтобы все сериализуемые классы явно объявляли значения serialVersionUID, поскольку вычисление serialVersionUID по умолчанию очень чувствительно к деталям класса, которые могут различаться в зависимости от реализаций компилятора, и, следовательно, могут привести к неожиданным исключениям InvalidClassExceptions во время десериализации. Поэтому, чтобы гарантировать согласованное значение serialVersionUID в различных реализациях Java-компилятора, сериализуемый класс должен объявить явное значение serialVersionUID. Также настоятельно рекомендуется, чтобы явные объявления serialVersionUID использовали модификатор private, где это возможно,

Если вы заметили, что мы использовали другое ключевое слово, которое является временным .

Если поле не сериализуемо, оно должно быть помечено как временное. Здесь мы отметили itemCostPrice как временный и не хотим, чтобы он был записан в файл

Теперь давайте посмотрим, как записать состояние объекта в файле, а затем прочитать его оттуда.

public class SerializationExample {

    public static void main(String[] args){
        serialize();
       deserialize();
    } 

    public static void serialize(){

         Item item = new Item(1L,"Pen", 12.55);
         System.out.println("Before Serialization" + item);

         FileOutputStream fileOut;
         try {
             fileOut = new FileOutputStream("/tmp/item.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut);
             out.writeObject(item);
             out.close();
             fileOut.close();
             System.out.println("Serialized data is saved in /tmp/item.ser");
           } catch (FileNotFoundException e) {

                  e.printStackTrace();
           } catch (IOException e) {

                  e.printStackTrace();
           }
      }

    public static void deserialize(){
        Item item;

        try {
                FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
                ObjectInputStream in = new ObjectInputStream(fileIn);
                item = (Item) in.readObject();
                System.out.println("Serialized data is read from /tmp/item.ser");
                System.out.println("After Deserialization" + item);
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
               e.printStackTrace();
        } catch (ClassNotFoundException e) {
               e.printStackTrace();
        }
     }
}

В приведенном выше примере мы видим пример сериализации и десериализации объекта.

Для этого мы использовали два класса. Для сериализации объекта мы использовали ObjectOutputStream. Мы использовали метод writeObject для записи объекта в файл.

Для десериализации мы использовали ObjectInputStream, который читает объект из файла. Он использует readObject для чтения данных объекта из файла.

Вывод приведенного выше кода будет выглядеть так:

Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]

Обратите внимание, что itemCostPrice из десериализованного объекта является нулевым поскольку оно не было записано.

Мы уже обсуждали основы Java-сериализации в первой части этой статьи.

Теперь давайте обсудим это глубоко и как это работает.

Сначала давайте начнем с serialversionuid.

serialVersionUID используется в качестве контроля версий в сериализуемом классе.

Если вы явно не объявите serialVersionUID, JVM сделает это за вас автоматически, основываясь на различных свойствах класса Serializable.

Алгоритм вычисления Java-версии (см. Подробнее здесь)

  1. Название класса.
    1. Модификаторы класса записываются как 32-разрядное целое число.
    2. Название каждого интерфейса отсортировано по имени.
    3. Для каждого поля класса, отсортированного по имени поля (кроме частных статических и частных переходных полей: имя поля. Модификаторы поля записываются в виде 32-разрядного целого числа. Дескриптор поля.
    4. Если инициализатор класса существует, запишите следующее: Имя метода,.
    5. Модификатор метода, java.lang.reflect.Modifier.STATIC, записывается как 32-разрядное целое число.
    6. Дескриптор метода, () V.
    7. Для каждого не приватного конструктора, отсортированного по имени метода и сигнатуре: Имя метода,. Модификаторы метода записаны как 32-разрядное целое число. Дескриптор метода.
    8. Для каждого не закрытого метода, отсортированного по имени метода и сигнатуре: Имя метода. Модификаторы метода записаны как 32-разрядное целое число. Дескриптор метода.
    9. Алгоритм SHA-1 выполняется в потоке байтов, созданных DataOutputStream, и выдает пять 32-битных значений sha [0..4]. Значение хеша составляется из первого и второго 32-битных значений дайджеста сообщения SHA-1. Если результат дайджеста сообщения, пять 32-битных слов H0 H1 H2 H3 H4, находится в массиве из пяти значений int с именем sha, значение хеш-функции будет вычислено следующим образом:
    long hash = ((sha[0] >>> 24) & 0xFF) |
>            ((sha[0] >>> 16) & 0xFF) << 8 |
>            ((sha[0] >>> 8) & 0xFF) << 16 |
>            ((sha[0] >>> 0) & 0xFF) << 24 |
>            ((sha[1] >>> 24) & 0xFF) << 32 |
>            ((sha[1] >>> 16) & 0xFF) << 40 |
>            ((sha[1] >>> 8) & 0xFF) << 48 |
>        ((sha[1] >>> 0) & 0xFF) << 56;

Алгоритм сериализации Java

Алгоритм сериализации объекта описан ниже:
1. Он записывает метаданные класса, связанного с экземпляром.
2. Он рекурсивно записывает описание суперкласса, пока не найдет java.lang.object .
3. Как только он заканчивает запись информации метаданных, он начинает с фактических данных, связанных с экземпляром. Но на этот раз он начинается с самого высшего суперкласса.
4. Он рекурсивно записывает данные, связанные с экземпляром, начиная с наименьшего суперкласса, до самого производного класса.

Что нужно иметь в виду:

  1. Статические поля в классе не могут быть сериализованы.

    public class A implements Serializable{
         String s;
         static String staticString = "I won't be serializable";
    }
  2. Если serialversionuid отличается в классе чтения, он выдаст InvalidClassExceptionисключение.

  3. Если класс реализует сериализуемый, то все его подклассы также будут сериализуемыми.

    public class A implements Serializable {....};
    
    public class B extends A{...} //also Serializable
  4. Если класс имеет ссылку на другой класс, все ссылки должны быть сериализуемыми, иначе процесс сериализации не будет выполнен. В таком случае NotSerializableException выбрасывается во время выполнения.

Например:

public class B{
     String s,
     A a; // class A needs to be serializable i.e. it must implement Serializable
}
Притам Банерджи
источник
1
«Сериализация - это процесс сериализации состояния объекта, представленного и сохраненного в виде последовательности байтов», не имеет смысла. Если serialVersionUIDотличается, он будет бросать InvalidClassException, а не ClassCastException. Нет необходимости тратить все это пространство на повторное serialVersionUIDвычисление. Документация цитируется, чрезмерно длинна, но не связана или не процитирована должным образом. Здесь слишком много пуха и слишком много ошибок.
Маркиз Лорн
«Сериализация - это процесс сериализации» остается бессмысленной.
маркиз Лорн
6

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

http://en.wikipedia.org/wiki/Serialization

Сыр Даниш
источник
«... чтобы его можно было хранить на жестком диске». Или передается по бинарному протоколу.
Джим Андерсон
4

Сериализация объектов Java

введите описание изображения здесь

Serializationэто механизм для преобразования графа Java-объектов в массив байтов для storage ( to disk file) или translation ( across a network), тогда с помощью десериализации мы можем восстановить граф объектов. Графики объектов корректно восстанавливаются с помощью механизма разделения ссылок. Но перед сохранением проверьте, совпадают ли serialVersionUID из файла ввода / сети и файла .class serialVersionUID. Если нет, киньте java.io.InvalidClassException.

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

Синтаксис serialVersionUID

// ANY-ACCESS-MODIFIER static final long serialVersionUID = (64-bit has)L;
private static final long serialVersionUID = 3487495895819393L;

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

Примечание. Настоятельно рекомендуется, чтобы все сериализуемые классы явно объявляли serialVersionUID since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementationsи, таким образом, могли привести к неожиданным конфликтам serialVersionUID во время десериализации, что приведет к сбою десериализации.

Проверка Сериализуемых Классов

введите описание изображения здесь


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

  • Класс должен реализовывать интерфейс java.io.Serializable для успешной сериализации своего объекта. Serializable - это маркерный интерфейс, используемый для информирования компилятора о том, что к классу, реализующему его, необходимо добавить сериализуемое поведение. Здесь виртуальная машина Java (JVM) отвечает за ее автоматическую сериализацию.

    временное ключевое слово: java.io.Serializable interface

    При сериализации объекта, если мы не хотим, чтобы определенные элементы данных объекта были сериализованы, мы можем использовать модификатор transient. Ключевое слово transient предотвратит сериализацию этого элемента данных.

    • Поля, объявленные как временные или статические, игнорируются процессом сериализации.

    ПРЕХОДЯЩАЯ & VOLATILE

    +--------------+--------+-------------------------------------+
    |  Flag Name   |  Value | Interpretation                      |
    +--------------+--------+-------------------------------------+
    | ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.|
    +--------------+--------+-------------------------------------+
    |ACC_TRANSIENT | 0x0080 | Declared transient; not written or  |
    |              |        | read by a persistent object manager.|
    +--------------+--------+-------------------------------------+
    class Employee implements Serializable {
        private static final long serialVersionUID = 2L;
        static int id;
    
        int eno; 
        String name;
        transient String password; // Using transient keyword means its not going to be Serialized.
    }
  • Реализация интерфейса Externalizable позволяет объекту взять на себя полный контроль над содержимым и форматом сериализованной формы объекта. Методы интерфейса Externalizable, writeExternal и readExternal, вызываются для сохранения и восстановления состояния объектов. При реализации классом они могут писать и читать свое собственное состояние, используя все методы ObjectOutput и ObjectInput. Объекты несут ответственность за обработку любых возникающих версий.

    class Emp implements Externalizable {
        int eno; 
        String name;
        transient String password; // No use of transient, we need to take care of write and read.
    
        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeInt(eno);
            out.writeUTF(name);
            //out.writeUTF(password);
        }
        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            this.eno = in.readInt();
            this.name = in.readUTF();
            //this.password = in.readUTF(); // java.io.EOFException
        }
    }
  • Только объекты , которые поддерживают интерфейс java.io.Serializable или java.io.Externalizable может быть written to/read from потоков. Класс каждого сериализуемого объекта кодируется, включая имя класса и сигнатуру класса, значения полей и массивов объекта и закрытие любых других объектов, на которые ссылаются исходные объекты.

Сериализуемый пример для файлов

public class SerializationDemo {
    static String fileName = "D:/serializable_file.ser";

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        Employee emp = new Employee( );
        Employee.id = 1; // Can not Serialize Class data.
        emp.eno = 77;
        emp.name = "Yash";
        emp.password = "confidential";
        objects_WriteRead(emp, fileName);

        Emp e = new Emp( );
        e.eno = 77;
        e.name = "Yash";
        e.password = "confidential";
        objects_WriteRead_External(e, fileName);

        /*String stubHost = "127.0.0.1";
        Integer anyFreePort = 7777;
        socketRead(anyFreePort); //Thread1
        socketWrite(emp, stubHost, anyFreePort); //Thread2*/

    }
    public static void objects_WriteRead( Employee obj, String serFilename ) throws IOException{
        FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );
        objectOut.writeObject( obj );
        objectOut.close();
        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            FileInputStream fis = new FileInputStream( new File( serFilename ) );
            ObjectInputStream ois = new ObjectInputStream( fis );
            Object readObject;
            readObject = ois.readObject();
            String calssName = readObject.getClass().getName();
            System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException

            Employee emp = (Employee) readObject;
            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void objects_WriteRead_External( Emp obj, String serFilename ) throws IOException {
        FileOutputStream fos = new FileOutputStream(new File( serFilename ));
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );

        obj.writeExternal( objectOut );
        objectOut.flush();

        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            // create a new instance and read the assign the contents from stream.
            Emp emp = new Emp();

            FileInputStream fis = new FileInputStream(new File( serFilename ));
            ObjectInputStream ois = new ObjectInputStream( fis );

            emp.readExternal(ois);

            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Сериализуемый пример по сети

Распределительный объект по разным адресным пространствам, либо в разных процессах на одном компьютере, либо даже на нескольких компьютерах, подключенных через сеть, но которые работают вместе, обмениваясь данными и вызывая методы.

/**
 * Creates a stream socket and connects it to the specified port number on the named host. 
 */
public static void socketWrite(Employee objectToSend, String stubHost, Integer anyFreePort) {
    try { // CLIENT - Stub[marshalling]
        Socket client = new Socket(stubHost, anyFreePort);
        ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
        out.writeObject(objectToSend);
        out.flush();
        client.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
// Creates a server socket, bound to the specified port. 
public static void socketRead(  Integer anyFreePort ) {
    try { // SERVER - Stub[unmarshalling ]
        ServerSocket serverSocket = new ServerSocket( anyFreePort );
        System.out.println("Server serves on port and waiting for a client to communicate");
            /*System.in.read();
            System.in.read();*/

        Socket socket = serverSocket.accept();
        System.out.println("Client request to communicate on port server accepts it.");

        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        Employee objectReceived = (Employee) in.readObject();
        System.out.println("Server Obj : "+ objectReceived.name );

        socket.close();
        serverSocket.close();
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

@видеть

Яши
источник
1
Когда вы добавляете ответ на шестилетний вопрос, на который уже есть несколько очень хороших ответов, вам нужно сделать намного лучше, чем какофонию орфографических ошибок.
Маркиз Лорн
@ejp Downvoting - инструмент для выражения вашего негативного мнения. Быть оскорбительным и грубым на границе недопустимо.
Константинос Чертурас
1
@KonstantinosChertouras Предоставление причин для понижения полезно для автора, и это мои причины, нравится им или нет, как вы.
Маркиз Лорн
Вам также необходимо избегать ошибок, таких как утверждение, что сериализация имеет целью безопасности. Это не так.
маркиз Лорн
@EJP Я обновил свой пост, исправив, что сериализация не в целях безопасности, но она используется для преобразования состояния объекта в любое хранилище и для возврата исходного состояния объекта с помощью SUID через механизм десериализации. JVM to JVM
Яша
3

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

Объект для сериализации должен реализовывать java.io.Serializableинтерфейс. Механизм сериализации по умолчанию для объекта записывает класс объекта, сигнатуру класса и значения всех непереходных и нестатических полей.

class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput,

ObjectOutputИнтерфейс расширяет DataOutputинтерфейс и добавляет методы для сериализации объектов и записи байтов в файл. ObjectOutputStreamРасширяет java.io.OutputStreamи реализует ObjectOutput интерфейс. Он сериализует объекты, массивы и другие значения в поток. Таким образом, конструктор ObjectOutputStreamзаписывается как:

ObjectOutput ObjOut = new ObjectOutputStream(new FileOutputStream(f));

Приведенный выше код был использован для создания экземпляра ObjectOutputкласса с помощью ObjectOutputStream( )конструктора, который принимает экземпляр класса в FileOuputStreamкачестве параметра.

ObjectOutputИнтерфейс используется путем реализации ObjectOutputStreamкласса. Создан ObjectOutputStreamдля сериализации объекта.

Десериализация объекта в Java

Противоположная операция сериализации называется десериализацией, т. Е. Извлечение данных из серии байтов называется десериализацией, которая также называется надуванием или демаршированием.

ObjectInputStreamрасширяет java.io.InputStreamи реализует ObjectInput интерфейс. Он десериализует объекты, массивы и другие значения из входного потока. Таким образом, конструктор ObjectInputStreamзаписывается как:

ObjectInputStream obj = new ObjectInputStream(new FileInputStream(f));

Выше код программы создает экземпляр ObjectInputStreamкласса для десериализации этого файла, который был сериализован ObjectInputStreamклассом. Приведенный выше код создает экземпляр, используя экземпляр FileInputStreamкласса, который содержит указанный файловый объект, который должен быть десериализован, поскольку ObjectInputStream()конструктору требуется входной поток.

Sindu
источник
2

Сериализация - это процесс превращения объекта Java в байтовый массив, а затем обратно в объект с сохраненным состоянием. Полезно для различных вещей, таких как отправка объектов по сети или кеширование на диск.

Прочитайте больше из этой короткой статьи, которая довольно хорошо объясняет программирование части процесса, а затем перейдите к Serializable javadoc . Вам также может быть интересно прочитать этот связанный вопрос .

Эско
источник
2

Верните файл как объект: http://www.tutorialspoint.com/java/java_serialization.htm

        import java.io.*;

        public class SerializeDemo
        {
           public static void main(String [] args)
           {
              Employee e = new Employee();
              e.name = "Reyan Ali";
              e.address = "Phokka Kuan, Ambehta Peer";
              e.SSN = 11122333;
              e.number = 101;

              try
              {
                 FileOutputStream fileOut =
                 new FileOutputStream("/tmp/employee.ser");
                 ObjectOutputStream out = new ObjectOutputStream(fileOut);
                 out.writeObject(e);
                 out.close();
                 fileOut.close();
                 System.out.printf("Serialized data is saved in /tmp/employee.ser");
              }catch(IOException i)
              {
                  i.printStackTrace();
              }
           }
        }

    import java.io.*;
    public class DeserializeDemo
    {
       public static void main(String [] args)
       {
          Employee e = null;
          try
          {
             FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn);
             e = (Employee) in.readObject();
             in.close();
             fileIn.close();
          }catch(IOException i)
          {
             i.printStackTrace();
             return;
          }catch(ClassNotFoundException c)
          {
             System.out.println("Employee class not found");
             c.printStackTrace();
             return;
          }
          System.out.println("Deserialized Employee...");
          System.out.println("Name: " + e.name);
          System.out.println("Address: " + e.address);
          System.out.println("SSN: " + e.SSN);
          System.out.println("Number: " + e.number);
        }
    }
Ран Адлер
источник
Это не отвечает на вопросы «что есть» или «пожалуйста, объясните».
маркиз Лорн
1

| * | Сериализация класса: преобразование объекта в байты и байты обратно в объект (десериализация).

class NamCls implements Serializable
{
    int NumVar;
    String NamVar;
}

| => Object-Serialization - это процесс преобразования состояния объекта в пару байтов.

  • | -> Реализуйте, когда вы хотите, чтобы объект существовал вне времени жизни JVM.
  • | -> Сериализованный объект может храниться в базе данных.
  • | -> Сериализуемые объекты не могут быть прочитаны и поняты людьми, поэтому мы можем добиться безопасности.

| => Объектная десериализация - это процесс получения состояния объекта и сохранения его в объекте (java.lang.Object).

  • | -> Перед сохранением своего состояния он проверяет, совпадают ли входной файл / сеть serialVersionUID с файлом serialVersionUID и файл .class.
    Если не выбрасывать исключение java.io.InvalidClassException.

| => Java-объект сериализуем, только если его класс или любой из его суперклассов

  • реализует либо интерфейс java.io.Serializable, либо
  • его подинтерфейс, java.io.Externalizable.

| => Статические поля в классе не могут быть сериализованы.

class NamCls implements Serializable
{
    int NumVar;
    static String NamVar = "I won't be serializable";;
}

| => Если вы не хотите сериализовать переменную класса, используйте ключевое слово transient

class NamCls implements Serializable
{
    int NumVar;
    transient String NamVar;
}

| => Если класс реализует сериализуемый, то все его подклассы также будут сериализуемыми.

| => Если класс имеет ссылку на другой класс, все ссылки должны быть сериализуемыми, иначе процесс сериализации не будет выполнен. В таком случае
NotSerializableException выбрасывается во время выполнения.

Суджай ООН
источник
0

Я предложу аналогию, чтобы потенциально помочь в укреплении концептуальной цели / практичности сериализации / десериализации объектов .

Я представляю сериализацию / десериализацию объекта в контексте попытки перемещения объекта через ливневую канализацию. Объект по существу «декомпозируется» или сериализуется в более модульные версии самого себя - в данном случае, серии байтов - для эффективного предоставления прохода через среду. В вычислительном смысле мы могли бы рассматривать путь, пройденный байтами через ливень, как сродни байту, проходящему через сеть. Мы трансмутируем наш объект, чтобы соответствовать более желаемому виду транспорта или формату. Сериализованный объект, как правило, будет храниться в двоичном файле, который впоследствии можно будет прочитать, записать или оба.

Возможно, когда наш объект сможет проскользнуть через сток в виде разложенной серии байтов, мы можем захотеть сохранить это представление объекта в виде двоичных данных в базе данных или на жестком диске. Однако основной вывод заключается в том, что при сериализации / десериализации у нас есть возможность оставить наш объект в двоичном виде после сериализации или «извлечь» исходную форму объекта путем выполнения десериализации.

Бенджамин Вестбург
источник