对象流

对象序列化与反序列化
本文介绍Java中对象的序列化与反序列化过程,包括实现Serializable接口的方法、序列化版本号的作用及如何通过transient关键字控制字段的序列化。

对象流


  1. 写对象数据:
    对象数据 ——>字节数据 对象的序列化
  2. 读取对象数据:
    字节数据 ——>对象数据 对象的反序列化

  3. Serializable接口

      此接口中没有任何内容,此接口是一个标志接口,此接口通常就是用于表示某个类的对象是可序列化的


  如果一个对象想要被序列化和反序列化,前提:该对象所属的类必须实现Serializable 接口


  将对象写入文件中去,到底是对象的什么数据写到了文件中?
此对象所属类的信息,对象中的数据,其他信息


Studnet类
public class Student implements Serializable{
   private int id;
   private String name;
   private int age;
   public Student() {
      super();
      // TODO Auto-generated constructor stub
   }
   public Student(int id, String name, int age) {
      super();
      this.id = id;
      this.name = name;
      this.age = age;
   }
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public int getAge() {
      return age;
   }
   public void setAge(int age) {
      this.age = age;
   }
   @Override
   public String toString() {
      return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
   }

   @Override
   public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + id;
      return result;
   }
   @Override
   public boolean equals(Object obj) {
      if (this == obj)
          return true;
      if (obj == null)
          return false;
      if (getClass() != obj.getClass())
          return false;
      Student other = (Student) obj;
      if (id != other.id)
          return false;
      return true;
   }

}
写对象数据
/**
 * 向文件中写入Student对象数据
 * @author adminitartor
 *
 */
public class WriteObectDemo {
   public static void main(String[] args) throws FileNotFoundException, IOException {
      //创建流对象
      ObjectOutputStream oos = new
          ObjectOutputStream(new
             FileOutputStream("oos.txt"));
      //写数据
      Student student = new Student(1, "tom", 23);
      oos.writeObject(student);
      //释放资源
      oos.close();
   }

}
读取对象数据
/**
 * 读取文件中的字节数据还原成对象数据
 * @author adminitartor
 *
 */
public class ReadObjectDemo {
   public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
      //创建流对象
      ObjectInputStream ois = new
             ObjectInputStream(new
                   FileInputStream("oos.txt"));
      //读取数据
      Student stu = (Student)ois.readObject();
      System.out.println(stu);

      //释放资源
      ois.close();
   }

}

对象序列化:

    •    对象是存在于内存中的。有时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输到另一台计算机上等等这样的操作。这时我们需要将对象转换为一个字节序列,而这个过程就称为对象序列化

反序列化:

    •   相反,我们有这样一个字节序列需要将其转换为对应的对象,这个过程就称为对象的反序列化。

反序列化的机制:

    •   当一个类实现了Serializable接口后,编译器会提示应当添加一个常量:serialVersionUID,这个常量标识当前类的序列化版本号.若不指定,编译器在编译当前类时会根据当前类的结构计算生成版本号,但是只要类的结构发生了变化,那么版本号就会改变.版本号决定着一个对象是否可以反序列化成功.

当对象输入流在将一个对象进行反序列化时会检查该对象的版本号与当前程序中这个类的版本号是否一致?

   若一致:反序列化成功,若当前类发生了改变,那么则还原依
然存在的属性.
*若不一致,则反序列化方法readObject会抛出异常.
  方法:
    写对象数据 -writerObject(Object)
    读取对象数据 -readObject() -Object
    
向文件中写入Student对象数据

 //创建流对象
      ObjectOutputStream oos = new
          ObjectOutputStream(new
             FileOutputStream("oos.txt"));
      //写数据
      Student student = new Student(1, "tom", 23);
      oos.writeObject(student);
      //释放资源
      oos.close();

读取文件中的字节数据还原成对象数据

//创建流对象
      ObjectInputStream ois = new
             ObjectInputStream(new
                   FileInputStream("oos.txt"));
      //读取数据
      Student stu = (Student)ois.readObject();
      System.out.println(stu);

      //释放资源
      ois.close();

  如果对一个类添加属性或减少属性,对已经写好的对象进行反序列化,出现什么问题?如何解决?
  出现的问题: 反序列化失败,抛出异常
  解决方案:在实现Serializable接口的类中,手动生成序列版本号
  

public class Student implements Serializable{
   /**
    *
    */
   private static final long serialVersionUID = 6711298969568631630L;
   private int id;
   private String name;
   private int age;
   private String gender;

案列:
  类:person
  属性:id name age desc
  要求: 将person 对象写入文件中时,desc 属性的值不 写入
  解决办法:使用transient关键字

public class Person implements Serializable {
   /**
    *
    */
   private static final long serialVersionUID = 403295796195916326L;
   private int id;
   private String name;
   private int age;
   private transient String desc;

  将Person对象写入文件,对象中的desc属性值
不写入,读取文件中的数据并打印到控制台

  //写对象数据
      //创建流对象
//    ObjectOutputStream oos = new
//           ObjectOutputStream(new
//                 FileOutputStream("person.txt"));
//    //写Person对象
//    Person person = new Person(12, "jack", 23, "聪明的,胖的");
//    oos.writeObject(person);
//   
//    //释放资源
//    oos.close();

      /*
       * 将person.txt中的对象数据还原
       */
      //创建流对象
      ObjectInputStream ois = new
             ObjectInputStream(new
                   FileInputStream("person.txt"));
      //读取对象数据 - 反序列化
      Person per = (Person)ois.readObject();
      System.out.println(per);
      //释放资源
      ois.close();

  transient关键字:
  用于修饰类中的成员变量
  当一个属性被transient修饰后,该属性在进行对象序列化时其值会被忽略.
  
  当一个对象是可序列化是,如果内部的成员有别的对象,那么,作为成员的其他对象一定也是可序列化的。

Person类
public class Person implements Serializable {
   /**
    *
    */
   private static final long serialVersionUID = 403295796195916326L;
   private int id;
   private String name;
   private int age;
   private transient String desc;
Worker类
public class Worker implements Serializable {
   /**
    *
    */
   private static final long serialVersionUID = 3406471866652587638L;
   private Person person;
   private String workId;
测试类
public class WorkerDemo {
   public static void main(String[] args) throws FileNotFoundException, IOException {
      /*
       * 将Worker对象写入文件中去
       */
      ObjectOutputStream oos = new
             ObjectOutputStream(new
                   FileOutputStream("worker.txt"));
      Person per = new Person(1001, "tom", 33, null);
      Worker worker = new Worker(per, "1213");

      oos.writeObject(worker);

      oos.close();

   }

}

反序列化原理图:
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值