2010-08-07 2 views
87

Что именно означает, что класс должен быть Serializable в Java? Или вообще, если на то пошло ...Что означает Serializable?

+10

@skaffman Вот что он говорит для класса 'Serializable': ' Сериализуемость класса включена классом, реализующим интерфейс java.io.Serializable. Классы, которые не реализуют этот интерфейс, не будут иметь своего сериализованного или десериализованного состояния. Все подтипы сериализуемого класса сами сериализуемы. Интерфейс сериализации не имеет методов или полей и служит только для определения семантики сериализации. « –

+26

Отличное объяснение, если вы уже знаете, что означают сериализованные и десериализованные значения. (Не комплимент.) Такие определения помогут вам лучше понять технику один раз, и только один раз вы уже знаете об этом. – Xonatron

ответ

92

Serialization хранит объект из памяти в последовательность бит, например, для сохранения на диск. Десериализация - это противоположность - чтение данных с диска для гидратации/создания объекта.

В контексте вашего вопроса это интерфейс, который, если он реализован в классе, этот класс может автоматически сериализоваться и десериализоваться различными сериализаторами.

+1

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

29

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

5

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

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

+4

Это не флаг для компилятора. Это флаг подсистемы Serialization во время выполнения. – EJP

+0

@EJP - Спасибо, не знал, что – AphexMunky

+0

С уважением, зачем писать, когда вы не знаете, что это правда? Вы также оставили «переходный». В общем, плохой ответ, извините. – EJP

8

Сериализация включает в себя сохранение текущего состояния объекта в потоке и восстановление эквивалентного объекта из этого потока. Поток функционирует как контейнер для объекта

0

Просто добавьте другие ответы и в отношении общности. Сериализация иногда называется архивированием, например, в Objective-C.

4

Сериализация - это способ хранения или записи объектов и данных в файлы. Используя классы ObjectOutputStream и FileOutputStream. Эти классы имеют свои конкретные методы для сохранения объектов. , как writeObject();

для четкого объяснения с цифрами. See Here for more info

1

Представить с другой точки зрения. Сериализация - это своего рода интерфейс, называемый «интерфейс-маркер». Интерфейс маркера - это интерфейс, который не содержит деклараций методов, но просто обозначает (или «метки») класс, который реализует интерфейс как имеющее какое-либо свойство. Если вы понимаете полиморфизм, это будет иметь очень большой смысл. В случае интерфейса маркера Serializable метод ObjectOutputStream.write (Object) завершится неудачно, если его аргумент не реализует интерфейс. Это потенциальная ошибка в Java, это могло бы быть ObjectOutputStream.write (Serializable)

Highly Recommended: Читаем пункт 37 из Effective Java Джошуа Блоха, чтобы узнать больше.

27

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

Допустим, у вас есть класс человека, как следующее:

public class Person implements java.io.Serializable { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    public String firstName; 
    public String lastName; 
    public int age; 
    public String address; 

    public void play() { 
     System.out.println(String.format(
       "If I win, send me the trophy to this address: %s", address)); 
    } 
    @Override 
    public String toString() { 
     return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName); 
    } 
} 

, а затем создать объект так:

Person william = new Person(); 
     william.firstName = "William"; 
     william.lastName = "Kinaan"; 
     william.age = 26; 
     william.address = "Lisbon, Portugal"; 

вы можете сериализацию этого объекта многих потоков. Я сделаю, что два потока:

Сериализация в стандартный вывод:

public static void serializeToStandardOutput(Person person) 
      throws IOException { 
     OutputStream outStream = System.out; 
     ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream); 
     stdObjectOut.writeObject(person); 
     stdObjectOut.close(); 
     outStream.close(); 
    } 

сериализации в файл:

public static void serializeToFile(Person person) throws IOException { 
     OutputStream outStream = new FileOutputStream("person.ser"); 
     ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream); 
     fileObjectOut.writeObject(person); 
     fileObjectOut.close(); 
     outStream.close(); 
    } 

Тогда:

десериализации из файла :

public static void deserializeFromFile() throws IOException, 
      ClassNotFoundException { 
     InputStream inStream = new FileInputStream("person.ser"); 
     ObjectInputStream fileObjectIn = new ObjectInputStream(inStream); 
     Person person = (Person) fileObjectIn.readObject(); 
     System.out.println(person); 
     fileObjectIn.close(); 
     inStream.close(); 
    } 
1

Сериализация: Запись состояния объекта в файл/сети или в любом месте. (Средняя поддерживаемая Java-форма форма в поддерживаемой форме или поддерживаемой в сети форме)

Deserialization: Чтение состояния объекта из файла/сети или где угодно. (Mean File/Сеть Поддерживаемые формы для Java Object Поддерживаемое Form)

4

Here is a detailed explanation of the Serialization: (мой собственный блог)

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

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

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

В современной современной архитектуре всегда необходимо сохранять состояние объекта, а затем извлекать его. Например, в 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», которое должно быть статическим, окончательным и длинным: ANY-ACCESS-MODIFIER статический конечный длинный serialVersionUID = 42L; Если сериализация класс не явно объявлять serialVersionUID, то сериализация выполнение будет вычислять значение serialVersionUID по умолчанию для этого класса на основе различных аспектов класса, как описано в сериализации Java (TM) объекта спецификацией. Тем не менее, настоятельно рекомендуется, чтобы все сериализуемые классы явно объявлять serialVersionUID значения, так как по умолчанию serialVersionUID вычисление очень чувствительно к классу деталей, которые могут варьироваться в зависимости от реализации компилятора, и таким образом, может привести к неожиданным InvalidClassExceptions во десериализации. Поэтому, чтобы гарантировать последовательное значение serialVersionUID в разных реализациях java-компилятора, сериализуемый класс должен объявить явное значение serialVersionUID. Также настоятельно рекомендует, чтобы явные объявления serialVersionUID, если это возможно, использовали частный модификатор , так как такие объявления относятся только к , сразу объявляющие поля class - 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 от десериализованного объекта нуля, как она была написана.

Смежные вопросы