Java序列化

2019-03-28 22:38|来源: 网络

Java序列化

Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。

将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。

整个过程都是Java虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

类ObjectInputStream 和ObjectOutputStream是高层次的数据流,它们包含序列化和反序列化对象的方法。

ObjectOutputStream 类包含很多写方法来写各种数据类型,但是一个特别的方法例外:

public final void writeObject(Object x) throws IOException

上面的方法序列化一个对象,并将它发送到输出流。相似的ObjectInputStream 类包含如下反序列化一个对象的方法:

public final Object readObject() throws IOException, 
                                 ClassNotFoundException

该方法从流中取出下一个对象,并将对象反序列化。它的返回值为Object,因此,你需要将它转换成合适的数据类型。

为了演示序列化在Java中是怎样工作的,我将使用之前教程中提到的Employee类,假设我们定义了如下的Employee类,该类实现了Serializable 接口。

public class Employee implements java.io.Serializable
{
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + name
                           + " " + address);
   }
}

请注意,一个类的对象要想序列化成功,必须满足两个条件:

该类必须实现 java.io.Serializable 对象。

该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。

如果你想知道一个Java标准类是否是可序列化的,请查看该类的文档。检验一个类的实例是否能序列化十分简答, 只需要查看该类有没有实现java.io.Serializable接口。


序列化对象

ObjectOutputStream 类用来序列化一个对象,如下的SerializeDemo例子实例化了一个Employee对象,并将该对象序列化到一个文件中。

该程序执行后,就创建了一个名为employee.ser文件。该程序没有任何输出,但是你可以通过代码研读来理解程序的作用。

注意: 当序列化一个对象到文件时, 按照Java的标准约定是给文件一个.ser扩展名。

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


反序列化对象

下面的DeserializeDemo程序反序列化在SerializeDemo程序中创建Employee对象。

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

以上程序编译运行结果如下所示:

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

这里要注意以下要点:

readObject() 方法中的try/catch代码块尝试捕获 ClassNotFoundException异常。对于JVM可以反序列化对象,它必须是能够找到字节码的类。如果JVM在反序列化对象的过程中找不到该类,则抛出一个 ClassNotFoundException异常。

注意,readObject()方法的返回值被转化成Employee引用。

当对象被序列化时,属性SSN的值为111222333,但是因为该属性是短暂的,该值没有被发送到输出流。所以反序列化后Employee对象的SSN属性为0。


转自网络  

相关问答

更多

延迟加载DbSet(Lazy loading DbSet)

EntityFramework在内部避免做一些在启动时需要做的昂贵的引导程序,直到它知道它需要它为止。 创建DbContext (以及其他)是在EF中触发一些可能代价高昂的活动的操作之一,这可能是(为什么)代码将其包装在Lazy以便如果调用代码不需要访问EF对象无论什么原因,都不会产生这样的代价。 本文对各种版本的EF启动性能有一些有用的了解: https : //msdn.microsoft.com/en-gb/data/hh949853.aspx 在这种情况下(并且不知道GitHub代码背后

WSO2 APIM GW错误消息无法发布油门事件(WSO2 APIM GW error message for not able to publish throttle event)

当您拥有Authentication:none资源时,这是一个已知问题。 这是在这里报道,并将在未来的版本中修复。 This is a known issue when you have Authentication:none for resources. It's reported here, and will be fixed in a future release.

JAVA如何通过mousePosition从JTabbedPane获取Tab(JAVA How to get Tab from JTabbedPane by mousePosition)

Component c = tab.getComponentAt(new Point(e.getX(), e.getY())); 你不想在你点击的地方获得组件。 您想从选定的选项卡中获取组件。 代码应该是: //int index = tab.getSelectedTab(); // oops, this was a typo int index = tab.getSelectedIndex(); Component c = tab.getComponentAt( index ); Comp

需要在jqgrid中显示默认排序列图标(Need to show the default sort column icon in jqgrid)

你的意思可能是以下我的老答案 。 演示或这个是您使用的。 您写道,您希望在默认排序列中看到突出显示的图标。 要解决此问题,您必须在网格中使用sortname选项。 定义.sortedColumnHeader > div CSS设置也很重要。 如果你在演示中这样做,那么一切都按预期工作。 You mean probably the following my old answer. The demo or this one which is what you use. You wrote that

kotlin是否支持在其定义文件之外创建一个实现接口的类?(Does kotlin support making a class implementing an interface outside of its definition file?)

不,它不受支持。 你是对的,这只是一个编译技巧。 为了使它们正确,有许多魔法应用于集合。 幸运的是开发者无法使用它。 文档中的特殊段落: https : //kotlinlang.org/docs/reference/java-interop.html#mapped-types No, it is not supported. You are right, that is only a compiler trick. There are lots of magic applied to the
java8新特征详解
java文件操作专题教程
JAVA概述
第一部分:java入门基础
第二部分:java常用类
第三部分:jdbc系列教程
第四部分:java高级特征

相关文章

更多

最近更新

更多