Java 序列化详解及简单实现实例

一、序列化

序列化定义:序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。

目的:

  1. 以某种存储形式使自定义对象持久化
  2. 将对象从一个地方传递到另一个地方

二、Java序列化

一个对象能够序列化的前提是实现Serializable接口。Serializable接口没有方法,更像是个标记。有了这个标记的Class就能被序列化机制处理。如下:

class myPoint implements Serializable{
}
 

JAVA反序列化不会调用任何构造器

序列化的控制:Externalizable。读写都交给你

  1. 要在方法writeExternal写入序列化的参数
  2. 要在方法readExternal读取反序列化的值
  3. 要有默认的构造方法(readExternal执行完成,再执行默认的构造器)
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException,ClassNotFoundException;
public class Point implements Externalizable {
  private int a;
  private int b;
  public Point(int a, int b) {
    this.a = a;
    this.b = b;
  }
  public Point() {
  }
  public String toString() {
    return a + " , " + b;
  } 

  public void writeExternal(ObjectOutput out) throws IOException {
    out.write(a);
    out.write(b);
  }
  public void readExternal(ObjectInput in) throws IOException,
      ClassNotFoundException {
    a = in.read();
    b = in.read();
  }
  public static void main(String[] args) throws IOException,
      ClassNotFoundException {
    String file = "d://1.txt";
    Point p = new Point(1, 2);
    System.out.println(p);
    FileOutputStream fos = new FileOutputStream(file);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(p);
    FileInputStream fis = new FileInputStream(file);
    ObjectInputStream ois = new ObjectInputStream(fis);
    Point pp = (Point) ois.readObject();
    System.out.println(pp);
  }
}
  1. transient关键字 关闭序列化自动进行。
  2. 不管你选择了哪种序列化形式,都要为自己编写的每个可序列化的类声明一个显示的序列版本UID(serial version UID)

三、序列化的问题

在effective Java中列举出了java序列化要注意的一些问题:

1.谨慎地设计实现Serializable接口

  1. 实现发布了就是一种承诺
  2. 如果一个类是为继承设计的,在‘允许子类实现Serializable接口'与‘禁止子类实现Serializable接口'取一个折中的方案是:提供一个可访问的无参构造器

2.保护性地编写 readObject()方法,因为readObject()是构建实例的入口。

不保护可能出现 构建了不满足要求的 实例

3.考虑自定义的序列化形式

  1. 逻辑内容 与 物理表示法
  2. 如果一个对象的 ‘物理表示法'等同于它的‘逻辑内容',可能就适用于使用默认的序列化形式。
  3. 如果有更好的 ‘物理表示法'在表示‘逻辑内容'则可以自定义序列化形式。
public class StringList implements Serializable {
  private transient int size = 0;
  private transient Entity head = null;
  public final void add(String str) {
    // ...
  }
  private static class Entity {
    String data;
    Entity next;
    Entity previous;
  }
  private void writeObject(ObjectOutputStream s) throws IOException {
    s.defaultWriteObject();
    s.write(size);
    for (Entity e = head; e != null; e = e.next) {
      s.writeObject(e.data);
    }
  }
  private void readObject(ObjectInputStream s) throws IOException,
      ClassNotFoundException {
    s.defaultReadObject();
    int num = s.read();
    for (int i = 0; i < num; i++) {
      this.add((String) s.readObject());
    }
  }
}

四、序列化代理模式

序列化机制提供的钩子函数有:

writeReplace writeObject  readObject  readResolve

  1. writeReplace:序列化的时候替换所要序列化的对象。
  2. writeObject:写入序列化的对象
  3. readObject:读取序列化的对象
  4. readResolve:最后返回序列化对象
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Date;
public final class Period implements Serializable {
  private static final long serialVersionUID = 100L;
  private final Date start;
  private final Date end;
  public Period(Date start, Date end) {
    this.start = new Date(start.getTime());
    this.end = new Date(end.getTime());
    if (this.start.compareTo(this.end) > 0) {
      throw new IllegalArgumentException(start + " after " + end);
    }
  }
  public Date start() {
    return new Date(start.getTime());
  }
  public Date end() {
    return new Date(end.getTime());
  }
  public String toString() {
    return start + " - " + end;
  }
  // 不给
  private Object writeReplace() {
    return new SerializationProxy(this);
  }
  private void readObject(ObjectInputStream stream)
      throws InvalidObjectException {
    throw new InvalidObjectException("proxy request");
  }
  private static class SerializationProxy implements Serializable {
    private final Date start;
    private final Date end;
    SerializationProxy(Period p) {
      this.start = p.start;
      this.end = p.end;
    }
    private Object readResolve() {
      return new Period(start, end);
    }
    private static final long serialVersionUID = 1000L;
  }
}

五、序列化算法

  1. 将对象实例相关的类元数据输出。
  2. 递归地输出类的超类描述直到不再有超类。
  3. 类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。
  4. 从上至下递归输出实例的数据

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 浅谈Java序列化和hessian序列化的差异

    在远程调用中,需要把参数和返回值通过网络传输,这个使用就要用到序列化将对象转变成字节流,从一端到另一端之后再反序列化回来变成对象. 既然前面有一篇提到了hessian,这里就简单讲讲Java序列化和hessian序列化的区别. 首先,hessian序列化比Java序列化高效很多,而且生成的字节流也要短很多.但相对来说没有Java序列化可靠,而且也不如Java序列化支持的全面.而之所以会出现这样的区别,则要从它们的实现方式来看. 先说Java序列化,具体工作原理就不说了,Java序列化会把要序列化

  • Java 序列化和反序列化实例详解

    Java 序列化和反序列化实例详解 在分布式应用中,对象只有经过序列化才能在各个分布式组件之间传输,这就涉及到两个方面的技术-发送者将对象序列化,接受者将对象反序列化,下面就是一个很好的例子! 1.实体-Employee import java.io.Serializable; public class Employee implements Serializable{ /** * */ private static final long serialVersionUID = 1L; publi

  • 序列化版本号serialVersionUID的作用_动力节点Java学院整理

    Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象. 序列化是Java中实现持久化存储的一种方法:为数据传输提供了线路级对象表示法. Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常. Eclipse中The

  • 浅谈java中为什么实体类需要实现序列化

    当客户端访问某个能开启会话功能的资源,web服务器就会创建一个HTTPSession对象,每个HTTPSession对象都会占用一定的内存,如果在同一个时间段内访问的用户太多,就会消耗大量的服务器内存,为了解决这个问题我们使用一种技术:session的持久化. 什么是session的持久化? web服务器会把暂时不活动的并且没有失效的HTTPSession对象转移到文件系统或数据库中储存,服务器要用时在把他们转载到内存. 把Session对象转移到文件系统或数据库中储存就需要用到序列化: jav

  • 详解Java 对象序列化和反序列化

    之前的文章中我们介绍过有关字节流字符流的使用,当时我们对于将一个对象输出到流中的操作,使用DataOutputStream流将该对象中的每个属性值逐个输出到流中,读出时相反.在我们看来这种行为实在是繁琐,尤其是在这个对象中属性值很多的时候.基于此,Java中对象的序列化机制就可以很好的解决这种操作.本篇就简单的介绍Java对象序列化,主要内容如下: 简洁的代码实现 序列化实现的基本算法 两种特殊的情况 自定义序列化机制 序列化的版本控制 一.简洁的代码实现 在介绍对象序列化的使用方法之前,先看看

  • java 中Spark中将对象序列化存储到hdfs

    java 中Spark中将对象序列化存储到hdfs 摘要: Spark应用中经常会遇到这样一个需求: 需要将JAVA对象序列化并存储到HDFS, 尤其是利用MLlib计算出来的一些模型, 存储到hdfs以便模型可以反复利用. 下面的例子演示了Spark环境下从Hbase读取数据, 生成一个word2vec模型, 存储到hdfs. 废话不多说, 直接贴代码了. spark1.4 + hbase0.98 import org.apache.spark.storage.StorageLevel imp

  • Java 序列化详解及简单实现实例

    一.序列化 序列化定义:序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数据. 目的: 以某种存储形式使自定义对象持久化 将对象从一个地方传递到另一个地方 二.Java序列化 一个对象能够序列化的前提是实现Serializable接口.Serializable接口没有方法,更像是个标记.有了这个标记的Class就能被序列化机制处理.如下: class myPoint implements Serializabl

  • Java 事务详解及简单应用实例

    Java事务的简单使用  Java事务在一些面试中会被问到. 面试的时候,我们首先要回答的是:事务能够保证数据的完整性和一致性. 如果功力深厚点的话:就说一些原理(任务开始前先设置不提交任务,在所有任务完成后再提交任务, 如果任务在中间断开,就执行回滚,撤销前面执行的任务),简单一点就举个的例子(比如存钱和取钱的问题. 比如:银行在两个账户之间转账,从A账户转入B账户1000元,系统先减少A账户的1000元,然后再为B账号增加1000元.如果全部执行成功,数据库处于一致性:如果仅执行完A账户金额

  • JAVA 注解详解及简单实例

    JAVA 注解详解及简单实例 何为注解 注解(Annotation)又称为元数据,在JDK1.5后引入,它的作用是: 生成文档  这是注解的原始用途,可以通过注解生成JavaDoc文档 跟踪代码的依赖性  可以通过注解替代配置文件,简化项目的配置.现有的许多框架都采用这个功能减少自己的配置. 编译检查  在编译时进行格式检查,例如@Override 基础注解 Java目前内置了三种标准注解,以及四种元注解.四种元注解负责创建其他的注解. 三种标准注解 @Override,表示当前的方法覆盖超类中

  • Java Cache详解及简单实现

     Java Cache详解及简单实现 概要: 最近在做spring的项目,想做一个缓存,访问数据库,定期来做数据更新 要实现两个功能 可以通过http请求来立刻刷新缓存 缓存可以通过自己配置的时间间隔来定期刷新 通过Controller来做 因为需要通过http来刷新缓存,所以第一个想法就是把缓存做成一个Controller Controller的实现 Controller最大的优势,就是可以通过Spring的配置,注入很多依赖,比如对Service的依赖,对数据库的依赖等. 大量的访问数据库跟

  • Android AOP 注解详解及简单使用实例(三)

    Android  注解 相关文章: Android AOP注解Annotation详解(一) Android AOP之注解处理解释器详解(二) Android AOP 注解详解及简单使用实例(三) 一.简介 在Android 里面 注解主要用来干这么几件事: 和编译器一起给你一些提示警告信息. 配合一些ide 可以更加方便快捷 安全有效的编写Java代码.谷歌出的support-annotations这个库 就是主要干这个的. 和反射一起 提供一些类似于spring 可配置的功能,方便简洁. 二

  • java 多态性详解及简单实例

    Java中多态性的实现 什么是多态 面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行为方式.(发送消息就是函数调用) 实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法. 多态的作用:消除类型之间的耦合关系. 现实中,关于多态的例

  • java 爬虫详解及简单实例

    Java爬虫 一.代码 爬虫的实质就是打开网页源代码进行匹配查找,然后获取查找到的结果. 打开网页: URL url = new URL(http://www.cnblogs.com/Renyi-Fan/p/6896901.html); 读取网页内容: BufferedReader bufr = new BufferedReader(new InputStreamReader(url.openStream())); 正则表达式进行匹配: tring mail_regex = "\\w+@\\w+

  • Java File类的详解及简单实例

    Java File类的详解及简单实例 1. File():构造函数,一般是依据文件所在的指定位置来创建文件对象.  CanWrite():返回文件是否可写. CanRead():返回文件是否可读. CompareTo(File pathname):检查指定文件路径间的顺序. Delet():从文件系统内删除该文件. DeleteOnExit():程序顺利结束时从系统中删除文件. Equals(Object obj):检查特定对象的路径名是否相等. Exists():判断文件夹是否存在. GetA

  • java 基础教程之多线程详解及简单实例

    java 多线程详解 在这篇文章里,我们关注多线程.多线程是一个复杂的话题,包含了很多内容,这篇文章主要关注线程的基本属性.如何创建线程.线程的状态切换以及线程通信. 线程是操作系统运行的基本单位,它被封装在进程中,一个进程可以包含多个线程.即使我们不手动创造线程,进程也会有一个默认的线程在运行. 对于JVM来说,当我们编写一个单线程的程序去运行时,JVM中也是有至少两个线程在运行,一个是我们创建的程序,一个是垃圾回收. 线程基本信息 我们可以通过Thread.currentThread()方法

  • java StringBuilder类的详解及简单实例

     java  StringBuilder类的详解及简单实例 实现代码: public class StringBuilderTest { /** * @param args */ public static void main(String[] args) { StringBuilder sb = new StringBuilder(); // 追加字符串 sb.append("java");//sb = "java" // 插入 sb.insert(0 , &qu

随机推荐