zoukankan      html  css  js  c++  java
  • java序列化

    下面的SerializationDemo.java中有一个简单的类Point,它实现了Serializable接口。在主类的main方法中生成该类的实例并存储在文件chap7_sample17.txt中,然后再从文件中读入并调用实例的方法。

      import java.io.*; public class SerializationDemo { public static void main(String[ ] args) throws IOException { FileOutputStream fos = null; ObjectOutputStream oos = null; FileInputStream fis = null; ObjectInputStream ois = null; //先写入对象(序列化)       try{ fos = new FileOutputStream("chap7_sample17.dat"); oos = new ObjectOutputStream(fos); oos.writeObject(new Point(23,94)); //写入对象       }catch(IOException e){ System.out.println("写对象错误。" + e.toString()); }finally{ if (fos != null){fos.close();} if (oos != null){oos.close();} } //再读出对象(反序列化)       try{ fis = new FileInputStream("chap7_sample17.dat"); ois = new ObjectInputStream(fis); Point aPoint; aPoint = (Point)ois.readObject(); //读出对象         aPoint.printStates(); //调用对象方法       }catch(IOException e){ System.out.println("读对象错误。" + e.toString()); }catch(ClassNotFoundException e){ System.out.println("读对象没找到类:" + e.toString()); }finally{ if (fis != null){fis.close();} if (ois != null){ois.close();} } } } //下面是类Point的定义,注意它实现了Serializable接口   class Point implements Serializable{ private int x = 0; //x坐标     private int y = 0; //y坐标     //下面这句话,请看程序后面的讲解     private static final long serialVersionUID = 2208L;     //两个构造函数     public Point() { x = 0; y = 0; } public Point(int newX, int newY) { x = newX; y = newY; }     //几个其他方法     void setX(int newX) {x = newX;} void setY(int newY) {y = newY;} int getX() {return x; } int getY() {return y; } void printStates() { System.out.print("x=" + x + ", y = " + y ); System.out.println(" by www.itsway.net"); } }

    编译并执行,结果如下图所示。

    Java教程

    可以看出,当把文件中的已经序列化的对象反序列化后,对象的方法可以像过去一样调用。在实际编程时,可以把上面的序列化和反序列话对象的代码写在两个程序中,比如网络上的发送者和接收者。发送者把对象写在文件中,然后吧文件发送给接收方,接收者对其进行反序列化,从而可恢复对象。

    如果用记事本打开chap7_sample17.dat,会发现它不可阅读。因此可以理解为Java对序列化的对象实现了加密,所以序列化还可以防止网络上的截获者获得有用信息。截获者如果事先不了解文件中包含了哪些序列化对象,是极难破解文件的。

    serialVersionUID

    在Point类中有这样一句话:

      private static final long serialVersionUID = 2208L;

    它是什么意思呢?
      顾名思义,serialVersionUID字段是“序列版本通用标示号”。它的访问属性可以是public、private、protected,这都无所谓,但必须是静态(static)、最终(final)的long型字段。它的定义格式为:

      任意访问修饰符 static final long serialVersionUID = 某个long值;

    所以在例子中定义它的访问属性是private,并给它赋了个随意的long值2208。
      serialVersionUID在类中不参与任何方法,也不应和类的其他字段有任何关系,所以对于类本身没有任何用处。如果不提供serialVersionUID字段,发送者的Java编译器会对可序列化类生成一个serialVersionUID值并发给接收者,它是根据类名、接口名、成员方法及属性等生成的一个64位哈希值。接收者加载该对象的类时,也会计算一个serialVersionUID值。如果这两个值相等,则可以反序列化;如果不相等,则会抛出InvalidClassException异常,反序列化会失败。所以即使编程者不提供这个字段,系统也会自动计算serialVersionUID值的。我估计Sun公司这样做,是为了防止文件在网络上被篡改。
      但是,发送者的Java编译器和接受者的Java编译器未必相同,不同编译器计算出来的serialVersionUID值可能不一样,这样在反序列化过程中可能会导致意外的InvalidClassException。所以为了保证serialVersionUID在不同的Java编译器具有同一个值,Java帮助文件强烈建议:可序列化的类最好声明一个字段serialVersionUID。这就是在例子中增加它的原因。

    讲到这里,本章该结束了。在讲解Java的输入输出方面,本教程下了极大的功夫,如果你曾经读过其他教程(网上和网下的)就会体会到这一点。I/O的两个重要应用是对ZIP文件、JAR文件进行读写。我们知道,Winzip是网络上常用的压缩和解压缩工具,压缩后的数据文件可以在Internet上快速传输;JAR文件格式则是Java提供的另一种文件压缩方式,也很常用。有兴趣的读者可以参看java.util.zip包和java.util.jar包的帮助文档,这两个包各包含一些相关的类,可实现压缩和解压缩。呵呵,这里就不多说啦。下一章开始,将全面进入图形界面的编程,那又是一个新世界

  • 相关阅读:
    软件产品案例分析(团队)
    Beta 冲刺 (2/7)
    Beta 冲刺 (1/7)
    机器学习笔记
    第一次作业
    机器学习第一个次个人作业
    软工实践个人总结
    第10组 Beta版本演示
    第10组 Beta冲刺(5/5)
    第10组 Beta冲刺(4/5)
  • 原文地址:https://www.cnblogs.com/seerlin/p/1015515.html
Copyright © 2011-2022 走看看