Що таке об'єктна серіалізація?


384

Що означає "серіалізація об'єкта"? Чи можете ви поясніть це, будь-якими прикладами?


2
У разі , якщо ви зацікавлені в реальному світі Java EE сценарій , в якому бере участь сериализации, глава тут: stackoverflow.com/q/2294551
BalusC

Відповіді:


400

Серіалізація - це перетворення об'єкта в ряд байтів, так що об'єкт може бути легко збережений до постійного сховища або переданий по потоку через комунікаційне посилання. Потім байт-потік можна десеріалізувати - перетворити на репліку оригінального об'єкта.


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 , ми можемо порівняти вихід, щоб побачити, у чому різниця.

Ось знімок екрана, що показує саме таку різницю:

alt текст

Чи можете ви помітити відмінності? ;)

Є додаткове відповідне поле в серіалізації Java: serialversionUID, але я думаю, це вже занадто довго, щоб покрити його.


1
@ Raam86 екземпляр є об'єктом сериализации. Ви можете вважати головним методом окрему програму, яка створює об'єкт типуSerializationSample
OscarRyz

2
@ raam86 - це перше твердження в основному методі: SerializationSample instance = new SerializationSample();тоді створюється вихід і записується об'єкт до цього виводу.
OscarRyz

1
Ой. Не пролетів досить близько. Чудово !!
raam86

1
@jacktrades Чому б не спробувати. Просто скопіюйте / вставте приклад і побачте, що "NotSerializableException" кидається :)
OscarRyz

1
@jacktrades, оскільки на комп’ютері не було сказано, що об'єкт може бути серіалізований :) що означає oos?
Кріс Беннетт

101

Сміли відповісти на 6-річне запитання, додавши лише дуже розуміння на високому рівні для людей, які не знайомі з Java

Що таке серіалізація?

Перетворення об'єкта в байти

Що таке десеріалізація?

Перетворення байтів назад в об’єкт (Десеріалізація).

Коли застосовується серіалізація?

Коли ми хочемо зберегти об’єкт. Коли ми хочемо, щоб об’єкт існував поза життя СВМ.

Приклад реального світу:

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

Як здійснюється серіалізація в Java.

  1. java.io.SerializableІнтерфейс реалізації (інтерфейс маркера, тому немає способу реалізації).

  2. Збережіть об'єкт: Використовуйте java.io.ObjectOutputStreamклас, потік фільтру, який є обгорткою навколо байтового потоку нижнього рівня (щоб написати Object у файлові системи або перенести сплющений об'єкт по мережевому проводу та відновлений з іншого боку).

    • writeObject(<<instance>>) - написати об’єкт
    • readObject() - читати серіалізований Об’єкт

Пам'ятайте:

Коли ви серіалізуєте об'єкт, буде збережено тільки стан об'єкта, а не файл або методи класу об'єкта.

Коли ви серіалізували 2-байтовий об'єкт, ви бачите 51-байтний серіалізований файл.

Крок, як об’єкт серіалізується та десеріалізується.

Відповідь за: Як він перетворив файл у 51 байт?

  • Спочатку записує магічні дані потоку серіалізації (STREAM_MAGIC = "AC ED" та STREAM_VERSION = версія JVM).
  • Потім він виписує метадані класу, пов'язані з екземпляром (довжина класу, назва класу, serialVersionUID).
  • Потім рекурсивно записує метадані надкласу, поки не знайде java.lang.Object.
  • Потім починається з фактичних даних, пов’язаних із екземпляром.
  • Нарешті записує дані об’єктів, пов'язаних із екземпляром, починаючи від метаданих до фактичного вмісту.

Якщо вас цікавить більш поглиблена інформація про серіалізацію Java, перейдіть за цим посиланням .

Редагувати : Ще одне добре посилання для читання.

Це дасть відповідь на кілька частих питань:

  1. Як не серіалізувати жодне поле в класі.
    Відповідь: використовуйте перехідне ключове слово

  2. Коли дочірній клас серіалізується, чи батьківський клас серіалізується?
    Відповідь: Ні, якщо батько не розширює поле батьківських інтерфейсів, не серіалізується.

  3. Коли батько серіалізується, чи дошкільний клас отримує серіалізацію?
    Відповідь: Так, за замовчуванням дочірній клас також отримує серіалізацію.

  4. Як уникнути серіалізації дитячого класу?
    Відповідь: а. Замініть метод writeObject і readObject та киньте NotSerializableException.

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

  5. Деякі класи на системному рівні, такі як Thread, OutputStream та його підкласи та Socket, не піддаються серіалізації.

3
дуже дякую за цю лаконічну відповідь, це було дуже корисно!
Нобі

21

Серіалізація - це взяття "живого" об'єкта в пам'ять і перетворення його у формат, який можна десь зберігати (наприклад, в пам'яті, на диску) і пізніше "дезаріалізувати" назад в живий об'єкт.


14

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

Незважаючи на те, що знаючи про структуру класів роботів та маючи серіалізовані дані, вчений Землі не зміг десеріалізувати дані, які можуть змусити роботів працювати.

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

Вчені Марса чекали повної оплати. Після того, як виплата була здійснена, вчені Марса поділилися послідовним перетворенням UID з вченими Землі. Вчений Землі встановив його для класу роботів, і все стало добре.


9

Серіалізація означає збереження об'єктів у Java. Якщо ви хочете зберегти стан об'єкта і хочете відновити стан пізніше (можливо, в іншому JVM), можна використовувати серіалізацію.

Зауважте, що властивості об'єкта будуть лише збережені. Якщо ви хочете знову воскресити об'єкт, у вас повинен бути файл класу, тому що зберігатимуться лише змінні учасника, а не функції члена.

наприклад:

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

Searializable - це маркерний інтерфейс, який вказує на те, що ваш клас є серіалізаційним. Інтерфейс маркера означає, що це просто порожній інтерфейс, і за допомогою цього інтерфейсу буде повідомлено JVM, що цей клас можна зробити серіалізаційним.


9

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

Ось детальне пояснення серіалізації : (мій власний блог)

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

Серіалізація - це процес збереження стану об'єкта. Він представлений і зберігається у вигляді послідовності байтів. Це може бути збережено у файлі. Процес зчитування стану об'єкта з файлу та відновлення його називається десеріалізацією.

У чому потреба серіалізації?

У сучасній архітектурі сучасності завжди є необхідність зберігати стан об'єкта, а потім отримувати його. Наприклад, в режимі Hibernate, щоб зберігати об’єкт, ми повинні зробити клас Serializable. Це означає, що після збереження стану об'єкта у вигляді байтів його можна перенести в іншу систему, яка потім може прочитати з цього стану та отримати клас. Стан об'єкта може надходити з бази даних або іншого jvm або з окремого компонента. За допомогою серіалізації ми можемо отримати стан Object.

Приклад коду та пояснення:

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

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", яке повинно бути статичним, остаточним і тривалим типу: ANY-ACCESS-MODIFIER статичний остаточний довгий serialVersionUID = 42L; Якщо серіалізаційний клас явно не оголошує serialVersionUID, тоді час виконання серіалізації буде обчислювати значення за замовчуванням serialVersionUID для цього класу на основі різних аспектів класу, як описано в специфікації об’єкта серіалізації Java (TM). Однак настійно рекомендується, щоб усі серіалізаційні класи явно декларували значення serialVersionUID, оскільки обчислення serialVersionUID за замовчуванням дуже чутливі до деталей класу, які можуть змінюватися залежно від реалізації компілятора, і, таким чином, можуть призвести до несподіваних InvalidClassExceptions під час десеріалізації. Отже, щоб гарантувати послідовне значення serialVersionUID у різних реалізаціях компілятора Java, серіалізаційний клас повинен оголосити явне значення serialVersionUID. Також настійно рекомендується, щоб явні serialVersionUID декларації використовували приватний модифікатор, де це можливо,

Якщо ви помітили, є ще одне нами ключове ключове слово, яке є тимчасовим .

Якщо поле не є серіалізаційним, воно повинно бути позначене тимчасовим. Тут ми позначили 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 в частині I цієї статті.

Тепер давайте обговоримо це глибоко і як це працює.

Спочатку почнемо з 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. Якщо в класі є посилання на інший клас, всі посилання повинні бути Serializable, інакше процес серіалізації не буде виконуватися. У такому випадку 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/Серіялізація


"... щоб він міг зберігатися на жорсткому диску." Або передається через двійковий протокол.
Джим Андерсон

4

Серіалізація об'єктів Java

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

Serializationце механізм перетворення графіка об’єктів Java в масив байтів для зберігання ( to disk file) або передачі ( across a network), то за допомогою десеріалізації ми можемо відновити графік об'єктів. Графіки об’єктів відновлюються правильно за допомогою механізму обміну посиланнями. Перед тим як зберігати, перевірте, чи однакові файли serialVersionUID з вхідного файлу / мережі та .class файлу serialVersionUID. Якщо ні, киньте a 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

    Під час серіалізації об’єкта, якщо ми не хочемо, щоб певні члени даних об'єкта були серіалізовані, ми можемо використовувати модифікатор перехідних процесів. Перехідне ключове слово запобігає серіалізації цього члена даних.

    • Поля, оголошені перехідними або статичними, ігноруються процесом серіалізації.

    Минуще & 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 і можуть бути повторно серіалізовані будь-яким СВМ. У цьому випадку стан об'єктів Java "в пам'яті" перетворюється в потік байтів. Цей тип файлу користувач не може зрозуміти. Це особливий тип об'єктів, тобто повторно використаний JVM (Java Virtual Machine). Цей процес серіалізації об'єкта також називають дефляцією або маршалом об'єкта.

Об'єкт, що підлягає серіалізації, повинен реалізувати 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класу. TheObjectOutputStream побудована для серіалізації об'єкта.

Десеріалізація об'єкта в Java

Протилежна операція серіалізації називається десеріалізацією, тобто вилучення даних із ряду байтів, відома як десеріалізація, яка також називається надуванням або незміненням.

ObjectInputStreamрозширює java.io.InputStreamта реалізує ObjectInput інтерфейс. Він десеріалізує об'єкти, масиви та інші значення з вхідного потоку. Таким чином конструктор ObjectInputStreamзаписується як:

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

Наведений вище код програми створює екземпляр ObjectInputStreamкласу для десеріалізації того файлу, який був серіалізований ObjectInputStreamкласом. Вищевказаний код створює екземпляр, використовуючи екземпляр FileInputStreamкласу, який містить вказаний об'єкт файлу, який повинен бути дезаріалізований, оскільки ObjectInputStream()конструктору потрібен вхідний потік.


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;
}

| => Об'єкт-серіалізація - це процес перетворення стану об'єкта в пару байтів.

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

| => Десеріалізація об'єкта - це процес отримання стану об'єкта та зберігання його в об'єкті (java.lang.Object).

  • | -> Перед зберіганням свого стану він перевіряє, чи є surialVersionUID формою вхідний файл / мережа та .class файл serialVersionUID однаковими.
    & nbsp & nbspЯкщо не кидайте java.io.InvalidClassException.

| => Об'єкт Java піддається серіалізації лише у разі його класу або будь-якого з його суперкласів

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

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

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

| => Якщо ви не хочете серіалізувати змінну класу, використовуйте перехідне ключове слово

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

| => Якщо клас реалізує серіалізаційний, то всі його підкласи також будуть серіалізаційними.

| => Якщо в класі є посилання іншого класу, всі посилання повинні бути Serializable, інакше процес серіалізації не буде виконуватися. У такому випадку
NotSerializableException викидається під час виконання.


0

Я запропоную аналогію, яка потенційно допоможе у закріпленні концептуальної мети / практичності серіалізації / десеріалізації об'єкта .

Я уявляю серіалізацію / десеріалізацію об'єкта в контексті спроби переміщення об'єкта через зливовий стік. Об'єкт по суті "розкладається" або серіалізується в більш модульні версії самого себе - в даному випадку - ряд байт - для ефективного дозволу проходу через носій. У обчислювальному сенсі ми могли розглядати шлях, пройдений байтами через зливовий стік, як подібний до байтів, що проходять через мережу. Ми переміщуємо наш об’єкт, щоб відповідати більш бажаному виду транспорту або формату. Серіалізований об'єкт зазвичай зберігається у двійковому файлі, який згодом може бути прочитаний, записаний у або обидва.

Можливо, як тільки наш об’єкт зможе проскочити через стік у вигляді розкладеної серії байтів, ми можемо захотіти зберегти це подання об’єкта як бінарних даних у базі даних або на жорсткому диску. Основним способом вибору є те, що при серіалізації / десеріалізації у нас є можливість залишити наш об’єкт у його бінарній формі після серіалізації, або "відновити" оригінальну форму об'єкта, виконавши десяріалізацію.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.