什么是对象序列化?

什么是“对象序列化”的意思? 你能用一些例子来解释吗?

序列化是将对象转换为一系列字节,以便将对象轻松保存到持久性存储器中,或通过通信链接进行stream式处理。 字节stream然后可以反序列化 – 转换成原始对象的副本。

您可以将序列化视为将对象实例转换为字节序列(根据实现情况可能是二进制或非二进制)的过程。

当你想通过networking传输一个对象数据,例如从一个JVM传输到另一个JVM时,这非常有用。

在Java中,序列化机制被构build到平台中,但是您需要实现Serializable接口来使对象可序列化。

您还可以通过将属性标记为瞬态来防止对象中的某些数据被序列化。

最后你可以重写默认的机制,并提供你自己的; 这可能适用于某些特殊情况。 要做到这一点,你可以使用java中的一个隐藏function 。

重要的是要注意,被序列化的是对象或内容的“价值”,而不是类定义。 因此方法不会被序列化。

这是一个非常基本的样本,带有评论以方便阅读:

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”被创build,我们可以看到后面发生了什么。

如果我们将someInteger的值更改为Integer.MAX_VALUE ,我们可以比较输出结果,看看有什么不同。

以下是截屏显示的不同之处:

替代文字

你能发现差异吗? ;)

在Java序列化中还有一个相关的字段: serialversionUID,但是我想这已经太长了以至于无法覆盖它。

敢于回答6年的问题,为刚接触Java的人增加了一个非常高层次的理解

什么是序列化?

将对象转换为字节和字节回到对象(反序列化)。

什么时候使用序列化?

当我们要坚持客体。 当我们希望对象在JVM的生命周期之外存在时。

真实世界的例子:

自动柜员机:当账户持有人试图通过自动柜员机从服务器提取资金时,提取资料等账户持有人信息将被序列化并发送到服务器,在该服务器上进行反序列化并用于执行操作。

如何在java中执行序列化。

  1. 实现java.io.Serializable接口(标记接口,所以没有方法来实现)。

  2. 坚持这个对象:使用java.io.ObjectOutputStream类,这是一个过滤stream,它是一个低级别字节stream的包装(将Object写入文件系统,或通过networking线传送扁平对象并在另一侧重新构build)。

    • writeObject(<<instance>>) – 写一个对象
    • readObject() – 读取一个序列化的Object

记得:

当你序列化一个对象时,只有对象的状态被保存,而不是对象的类文件或方法。

当您序列化2个字节的对象时,您会看到51个字节的序列化文件。

步骤如何对象序列化和反序列化。

回答:它是如何转换为51字节的文件?

  • 首先写入序列化stream魔法数据(STREAM_MAGIC =“AC ED”和STREAM_VERSION = JVM的版本)。
  • 然后它写出与实例关联的类的元数据(类的长度,类的名称,serialVersionUID)。
  • 然后recursion地写出超类的元数据直到findjava.lang.Object
  • 然后从与实例关联的实际数据开始。
  • 最后,将从元数据开始的与实例关联的对象的数据写入实际内容。

如果您对更多有关Java序列化的信息感兴趣,请查看此链接 。

编辑 :一个更好的链接来阅读。

这将回答一些常见的问题:

  1. 如何不在课堂上序列化任何领域。
    Ans:使用瞬态关键字

  2. 当子类被序列化父类被序列化?
    Ans:不,如果父母不扩展Serializable接口父母字段不会被序列化。

  3. 当父母序列化子类获取序列化?
    Ans:是的,默认情况下,子类也被序列化。

  4. 如何避免子类被序列化?
    答:a。 覆盖writeObject和readObject方法并抛出NotSerializableException

    湾 你也可以标记所有在子类中的瞬态。

  5. 某些系统级别的类(如Thread,OutputStream及其子类和Socket)不可序列化。

序列化是在内存中的一个“活”的对象,并将其转换为可以存储在某个地方的格式(例如在内存中,在磁盘上),然后“反序列化”回活的对象。

我喜欢@OscarRyz提供的方式。 虽然在这里我继续最初由@amitgupta编写的序列化的故事 。

即使知道机器人的类别结构和序列化的数据,地球的科学家也无法对可以使机器人工作的数据进行反序列化。

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

火星的科学家正在等待完整的付款。 一旦付款完成,火星的科学家们与地球科学家分享了一系列的统一标识符 。 地球的科学家把它设置为机器人课,一切都变好了。

序列化意味着在java中持久化对象。 如果想要保存对象的状态,并希望稍后重新构build状态(可能在另一个JVM中),则可以使用序列化。

请注意,对象的属性只会被保存。 如果你想再次复活对象,你应该有类文件,因为成员variables只会被存储,而不是成员函数。

例如:

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

Searializable是一个标记接口,标记你的类是可序列化的。 标记接口意味着它只是一个空的接口,使用该接口将通知JVM该类可以被序列化。

序列化是将对象的状态转换为位的过程,以便将其存储在硬盘上。 当你反序列化同一个对象时,它将在后面保持它的状态。 它可以让你重新创build对象,而无需手动保存对象的属性。

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

我的两分钱从我自己的博客:

这里是序列化的详细解释 :(我自己的博客)

连载:

序列化是坚持对象状态的过程。 它以字节序列的forms表示和存储。 这可以存储在一个文件中。 从文件中读取对象的状态并恢复它的过程称为反序列化。

什么是序列化的需要?

在现代架构中,总是需要存储对象状态,然后检索它。 例如在Hibernate中,要存储一个对象,我们应该使类Serializable。 它的作用是,一旦对象状态以字节的forms保存,它可以被传送到另一个系统,然后可以从状态中读取和检索类。 对象状态可以来自数据库或不同的jvm,也可以来自不同的组件。 在序列化的帮助下,我们可以检索对象状态。

代码示例和说明:

首先让我们来看看Item类:

 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的variables被初始化为Longvariables。 此编号由编译器根据类的状态和类属性进行计算。 这是帮助jvm在从文件读取对象状态时识别对象状态的数字。

为此,我们可以看看官方的Oracle文档:

序列化运行时与每个可序列化的类关联一个称为serialVersionUID的版本号,在反序列化过程中使用该版本号来validation序列化对象的发送者和接收者是否已经为该对象加载了关于序列化兼容的类。 如果接收者已经为与对应的发送者类具有不同serialVersionUID的对象加载了类,则反序列化将导致InvalidClassExceptionexception。 一个可序列化的类可以通过声明一个名为“serialVersionUID”的字段声明自己的serialVersionUID,该字段必须是static,final和longtypes的:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; 如果可序列化类没有显式声明serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。 但是,强烈build议所有可序列化的类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类的详细信息高度敏感,这可能因编译器实现而异,因此在反序列化期间可能会导致意外的InvalidClassException。 因此,为了保证在不同的java编译器实现中保持一致的serialVersionUID值,可序列化的类必须声明一个显式的serialVersionUID值。 还强烈build议显式serialVersionUID声明尽可能使用private修饰符,因为这样的声明仅适用于立即声明的类 – serialVersionUID字段作为inheritance成员是无用的。

如果你已经注意到有另一个关键字,我们已经使用,这是短暂的

如果某个字段不可序列化,则必须标记为瞬态。 在这里,我们将itemCostPrice标记为transient,并且不希望将其写入文件中

现在让我们来看看如何在文件中写入一个对象的状态,然后从那里读取它。

 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被用作Serializable类中的版本控制。

如果你没有显式地声明一个serialVersionUID,那么JVM就会根据Serializable类的各种属性自动为你做。

Java的计算serialversionuid的algorithm (在这里阅读更多的细节)

  1. 类名称。
    1. 类修饰符写成32位整数。
    2. 每个接口的名称按名称sorting。
    3. 对于按字段名sorting的类的每个字段(私有静态和私有瞬态字段除外:字段的名称。字段的修饰符被写为32位整数。字段的描述符。
    4. 如果存在类初始化程序,请写出以下内容:方法的名称。
    5. 该方法的修饰符java.lang.reflect.Modifier.STATIC,写为32位整数。
    6. ()V的描述符。
    7. 对于按方法名称和签名sorting的每个非私有构造函数:方法名称。 该方法的修饰符被写为32位整数。 方法的描述符。
    8. 对于按方法名称和签名sorting的每个非私有方法:方法的名称。 该方法的修饰符被写为32位整数。 方法的描述符。
    9. SHA-1algorithm在由DataOutputStream生成的字节stream上执行,并生成五个32位值sha [0..4]。 散列值由SHA-1消息摘要的第一个和第二个32位值组装而成。 如果消息摘要的结果是五个32位字H0H1H2H3H4,它们是一个名为sha的五个int值的数组,则哈希值计算如下:
  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的序列化algorithm

序列化对象的algorithm如下所述:
1.它写出与实例关联的类的元数据。
2.recursion地写出超类的描述,直到findjava.lang.object
3.一旦它完成了元数据信息的写入,它就会从与实例关联的实际数据开始。 但这一次,它从最高级的超类开始。
4.recursion地写入与实例相关的数据,从最less的超类开始到派生最多的类。

要记住的事情:

  1. 类中的静态字段不能被序列化。

     public class A implements Serializable{ String s; static String staticString = "I won't be serializable"; } 
  2. 如果serialversionuid在读取类中不同,它将抛出一个InvalidClassExceptionexception。

  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 ie it must implement Serializable } 

序列化是将对象保存在存储介质(如文件或内存缓冲区)中或以二进制forms通过networking连接传输的过程。 序列化的对象是独立于JVM的,可以被任何JVM重新序列化。 在这种情况下,“内存中”Java对象状态被转换成字节stream。 这种types的文件不能被用户理解。 它是一种特殊types的对象,即由JVM(Java虚拟机)重用。 序列化对象的这个过程也被称为放气或编组对象。

要序列化的对象必须实现java.io.Serializable接口。 对象的默认序列化机制写入对象的类,类签名以及所有非瞬态和非静态字段的值。

 class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput, 

ObjectOutput接口扩展了DataOutput接口,并添加了序列化对象和将字节写入文件的方法。 ObjectOutputStream扩展java.io.OutputStream并实现ObjectOutput接口。 它将对象,数组和其他值序列化为stream。 因此ObjectOutputStream的构造函数写成:

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

上面的代码已经用于使用ObjectOutputStream( )构造函数创buildObjectOutput类的实例,该构造函数将FileOuputStream的实例作为参数。

ObjectOutput接口用于实现ObjectOutputStream类。 ObjectOutputStream构造为序列化对象。

在java中反序列化一个对象

序列化的相反操作称为反序列化,即从一系列字节中提取数据称为反序列化(deserialization),也称为膨胀或解组(unmarshalling)。

ObjectInputStream扩展java.io.InputStream并实现ObjectInput接口。 它从inputstream反序列化对象,数组和其他值。 因此ObjectInputStream的构造函数写成:

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

上面的程序代码创buildObjectInputStream类的实例,以反序列化由ObjectInputStream类序列化的文件。 上面的代码使用FileInputStream类的实例创build实例, FileInputStream类包含了必须反序列化的指定文件对象,因为ObjectInputStream()构造函数需要inputstream。

序列化是将一个Java对象转换成字节数组,然后以保留状态再次回到对象中的过程。 对于通过networking发送对象或将东西caching到磁盘等各种东西都很有用。

从这篇简短的文章中可以看到更多的内容,它解释了程序的编程部分,然后移到了Serializable javadoc 。 您可能也有兴趣阅读这个相关的问题 。

以对象forms返回文件: 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); } } 

Java提供了一种称为对象序列化的机制,其中对象可以表示为包含对象数据的字节序列,以及有关对象types和存储在对象中的数据types的信息。 它主要用于在networking上传送对象的状态(称为编组)。

序列化(对象的)

在数据存储和传输的情况下,序列化是将数据结构或对象状态转换为可以存储的格式(例如,在文件或存储缓冲区中,或通过networking连接链路传送)和“复活“(反序列化)稍后在同一个或另一个计算机环境中。

系列化

  • 对象序列化是将对象的状态转换为字节stream的过程,所以序列化对象不能被人读取和理解,因此我们可以获得安全性。
  • 对象反序列化是获取对象的状态并将其存储到对象(java.lang.Object)中的过程。 但在存储其状态之前,请检查天气serialVersionUID表单的input文件/networking和.class文件的serialVersionUID是否相同。 如果不是抛出java.io.InvalidClassException。
  • 在提供可串行化接口(标记接口)的实现时,我们正在向编译器提供信息,以使用Java序列化机制来序列化此对象。
  • 一个Java对象只能被序列化。 如果其类或其任何超类实现了java.io.Serializable接口或其子接口java.io.Externalizable。

类阻碍了可序列化接口

 class Employee implements Serializable{ private static final long serialVersionUID = 2L; int eno; String name; static int id; // static information belongs to Entire-Class not for a perticular-object. but we can access through object. transient String password; // sensitive information private String classlevel; public String getClasslevel() { return classlevel; } public void setClasslevel(String classlevel) { this.classlevel = classlevel; } } 

主要类

 public class SrializationDemo { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { Employee e = new Employee(); e.eno = 12; e.name = "Yash"; e.password = "confidential"; e.id = 19; e.setClasslevel("Class Spesific data"); serialization_TXT(e); // Serializable obects cannot read and understood by humans. de_serialization(); } public static void serialization_TXT(Object o) throws IOException{ FileOutputStream fileOut = new FileOutputStream(new File("SerializationOut.txt")); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(o); // To store any object via serialization mechanism we call readoject() / writeObect() out.close(); fileOut.close(); System.out.println("Data Stored in SerializationOut.txt file"); } public static void de_serialization() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { FileInputStream fileIn = new FileInputStream(new File("SerializationOut.txt")); ObjectInputStream in = new ObjectInputStream(fileIn); Object o = in.readObject(); // Employee e = (Employee) Class.forName(o.getClass().getName()).newInstance(); // creating new object. String className = o.getClass().getName();// First Find the incoming Object Name, then type cast. Employee e = (Employee) o; // then type cast to that Correct-Class-type. So that we can get data and store it into this current object. // java.io.InvalidClassException: core.Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2 System.out.println(e.eno + "\t" +e.name +"\t" + e.password + "\t" + e.id +"\n"+ e.getClasslevel()); } } 
  • 我们使用transient关键字,当成员variables被持久化为字节stream时,成员variables不被序列化(这样对象不会被存储到文件中或通过networking传输)。

这个问题也可以让你理解一个关于Serialization的小技巧:

如果我们创build所有的java对象,会出现什么问题Serializable由于Serializable是一个空的interface ,Java提供了强大的序列化,一旦你添加了Serializable实现 – 为什么它们没有使所有的东西都可序列化,就这样呢?

答案可以在“ 为什么Java需要Serializable接口? ”中find,它描述了这可能导致安全问题和封装中断。

| * | 序列化类:将对象转换为字节和字节回到对象(反序列化)。

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

对象序列化是将对象状态转换为字节stream的过程。

  • | – >当您希望对象在JVM的生命周期之外存在时实现。
  • | – > Serilized Object可以存储在数据库中。
  • | – >可序列化的obects不能被人类阅读和理解,所以我们可以实现安全性。

对象反序列化是获取对象的状态并将其存储到对象(java.lang.Object)中的过程。

  • | – >在存储其状态之前,检查天气serialVersionUIDforms的input文件/networking和.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";; } 

| =>如果你不想序列化一个类的variables使用transient关键字

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

| =>如果一个类实现了可串行化,那么它的所有子类也将是可序列化的。

| =>如果一个类有另一个类的引用,那么所有的引用必须是Serializable,否则序列化过程将不会被执行。 在这种情况下,
在运行时抛出NotSerializableException。

我从这里find了这个好的答案:

想象一下,你想保存一个或多个对象的状态。 如果Java没有序列化,则必须使用其中一个I / O类来写出所有要保存的对象的实例variables的状态。 最糟糕的部分是试图重build与您试图保存的对象几乎完全相同的新对象。 你需要自己的协议来处理你写的每一个对象的状态,或者你可以用错误的值设置variables。 例如,假设您存储了一个具有高度和重量的实例variables的对象。 在保存对象的状态时,可以将文件中的高度和重量写成两个整数,但写入顺序至关重要。 重新创build对象会非常容易,但混合高度和重量值 – 使用保存的高度作为新对象重量的值,反之亦然。 序列化的目的是帮助我们实现我们刚刚看到的更复杂的情景。

使用ObjectOutputStreamObjectInputStream

基本序列化的神奇性只发生在两个方法上:一个序列化对象并将它们写入stream,另一个从stream中读取并反序列化对象。

 ObjectOutputStream.writeObject() - serialize and write ObjectInputStream.readObject() - read and deserialize 

java.io.ObjectOutputStream和java.io.ObjectInputStream类被认为是java.io包中的高级类,正如我们在前一章中学到的那样,意味着你将把它们包装在低级类中,如java.io.FileOutputStream和java.io.FileInputStream。 这里有一个小程序,它创build一个对象,对它进行序列化,然后对其进行反序列化:

 import java.io.*; class Car implements Serializable { } // 1 public class SerializeCar { public static void main(String[] args) { Car c = new Car(); // 2 try { FileOutputStream fs = new FileOutputStream("testSer.ser"); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject(c); // 3 os.close(); } Catch (Exception e) { e.printStackTrace(); } try { FileInputStream fis = new FileInputStream("testSer.ser"); ObjectInputStream ois = new ObjectInputStream(fis); c = (Car) ois.readObject(); // 4 ois.close(); } Catch (Exception e) { e.printStackTrace(); } } } 

让我们来看看这个例子中的关键点:

  1. 我们声明Car类实现了Serializable接口。 可串行化是一个标记接口; 它没有实施的方法。

  2. 我们做一个新的Car对象,我们知道它是可序列化的。

  3. 我们通过调用writeObject()方法来序列化Car对象c。 首先,我们必须将所有与I / O相关的代码放在try / catch块中。 接下来,我们必须创build一个FileOutputStream来写入对象。 然后,我们将FileOutputStream包装在一个ObjectOutputStream中,该ObjectOutputStream是具有我们所需的魔术序列化方法的类。 请记住writeObject()的调用执行两个任务:它序列化对象,然后将序列化的对象写入文件。

  4. 我们通过调用readObject()方法对Car对象进行反序列化。 readObject()方法返回一个Object,所以我们必须将反序列化的对象转换回Car。 再次,我们不得不经过典型的I / O环境来设置它。 – 查看更多