Java从零开始学三十九(对象序列化)

王朝学院·作者佚名  2016-05-28
窄屏简体版  字體: 小  |  中  |  大  |  超大  

java从零开始学三十九(对象序列化)一、序列化将对象的状态存储到特定存储介质中的过程

对象序列化,就是把一个对象变为二进制的数据流的一种方法,通过对象序列化可以方便的实现对象的传输或存储。序列化保存对象的“全景图”,构建对象的“全景天窗”.如果一个类的对象想被序列化,则对象所在的类必须实现java.io.Serializable接口二、对象的序列化和反序列化要想完成对象的输入或输出,还必须依靠对象输出流(ObjectOutputStream)和对象输入流(ObjectInputStream)使用对象输出流输出序列化对象的步骤,有时也称为序列化,而使用对象输入流读入对象的过程,有时也称为反序列化序列化步骤:创建一个对象输出流ObjectOutputStreamwriteObject()方法输出序列化对象反序列化步骤:

创建一个对象输入流ObjectInputStreamreadObject()方法读取流中的对象三、对象输出流(ObjectOutputStream)和对象输入流(ObjectInputStream)3.1、对象输出流:ObjectOutputStreamNo.

方法或常量

类型

描述

1

public ObjectOutputStream(OutputStream out) throws IOException

构造

传入输出的对象

2

public final void writeObject(Object obj) throws IOException

普通

输出对象

此类的使用形式与PRintStream非常的相似,在实例化时也需要传入一个OutputStream的子类对象,之后根据传入的OutputStream子类的对象不同,输出的位置也不同。3.2、对象输入流:ObjectInputStreamNo.

方法或常量

类型

描述

1

public ObjectInputStream(InputStream in) throws IOException

构造

构造输入对象

2

public final Object readObject() throws IOException, ClassNotFoundException

普通

从指定位置读取对象

此类也是InputStream的子类,与PrintStream类的使用类似,此类同样需要接收InputStream类的实例才可以实例化四、transient关键字当使用Serializable接口实现序列化操作时,如果一个对象中的某个属性不希望被序列化的话,则可以使用transient关键字进行声明import java.io.Serializable;public class Person implements Serializable { // 此类的对象可以被序列化 private transient String name; // 此属性将不被序列化 private int age; // 此属性将被序列化 public Person(String name, int age) { this.name = name; this.age = age; } public String toString() { // 覆盖toString(),输出信息 return "姓名:" + this.name + ";年龄:" + this.age; }}

五、实现反序列化注意事项反序列化过程无需要使用构造器生成对象按顺序反序列化恢复对象父类Serializable或者存在无参数构造方法六、例子package com.pb.serializable;import java.io.Serializable;/* * 学生类 并实现接口Serializable接口,使用之可以序列化 *//* * 序列化 * 1.创建一个对象,这个对象将被序列化,并写入文件中,前提是这个类实现了Serializable接口 * 2.实例化ObjectOutputStream的对象 * 3.调用ObjectOutputStream的writerObject()方法,将对象写入流中 * 4.关闭流 * transient关键字 * 可以保护对象中的敏感信息不被写入到文件中 * 反序列化 * 1.实例化ObjectInputStream对象 * 2.调用ObjectInputStream的readObject()方法,获取对象时,要进行强制类型转换 * 3.关闭流 */public class Student implements Serializable { private String name; // 姓名 private int age; // 年龄 private String gender; // 性别 private transient String passWord; // 密码属性不能被序列化 // 构造方法 public Student() { // 无参 } // 有参数 public Student(String name, int age, String gender, String password) { this.name = name; this.age = age; this.gender = gender; this.password = password; } //getter、setter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age>0&&age<150) this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { if(gender.equals("男") || gender.equals("女")) this.gender = gender; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } // 自我介绍 public void say() { System.out.println("姓名:" + this.name + "\t年龄:" + this.age + "\t性别:" + this.gender+"\t密码 : "+this.password); }}

序列化:

package com.pb.serializable;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.util.ArrayList;import java.util.List;/* * 序列化 * 1.创建一个对象,这个对象将被序列化,并写入文件中,前提是这个类实现了Serializable接口 * 2.实例化ObjectOutputStream的对象 * 3.调用ObjectOutputStream的writerObject()方法,将对象写入流中 * 4.关闭流 * transient关键字 * 可以保护对象中的敏感信息不被写入到文件中 */public class SerializableObj { public static void main(String[] args) { try { //1.声明一个文件输出流 FileOutputStream fos = new FileOutputStream("d:/test/obj.txt"); //2.声明ObjectOutputStream流对象 ObjectOutputStream oos=new ObjectOutputStream(fos); //也可以2步合一步 //ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("d:/test/obj.txt")); Student stu1=new Student("张三", 23, "男", "123456"); Student stu2=new Student("李四", 24, "女", "123123"); Student stu3=new Student("王五", 25, "男", "123321"); Student stu4=new Student("赵六", 26, "男", "999999"); //创建集合并添加 List<Student> list=new ArrayList<Student>(); list.add(stu1); list.add(stu2); list.add(stu3); list.add(stu4); //3.将student对象序列化,写入输出oos流 oos.writeObject(stu1); oos.writeObject(stu2); oos.writeObject(stu3); oos.writeObject(stu4); oos.writeObject(list); //4.关闭流 oos.close(); fos.close(); System.out.println("=======序列化完成======"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}

反序列化:

package com.pb.serializable;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.util.List;/* * 反序列化 * 1.实例化ObjectInputStream对象 * 2.调用ObjectInputStream的readObject()方法,获取对象时,要进行强制类型转换 * 3.关闭流 */public class ReadSerializableObj { public static void main(String[] args) { try { //1.声明一个文件输出流 FileInputStream fis = new FileInputStream("d:/test/obj.txt"); //2.实例化ObjectInputStream ObjectInputStream ois=new ObjectInputStream(fis); //也可以全2为一 //ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/test/obj.txt")); //3.声明一个Student对象和集合 System.out.println("=====反序列化学生对象======="); Student stu1= (Student) ois.readObject(); stu1.say(); Student stu2= (Student) ois.readObject(); stu2.say(); Student stu3= (Student) ois.readObject(); stu3.say(); Student stu4= (Student) ois.readObject(); stu4.say(); System.out.println("=====反序列化集合对象======="); List<Student> list=(List<Student>) ois.readObject(); for (Student s : list) { s.say(); } //4.关闭流 ois.close(); fis.close(); System.out.println("====反序列完成===="); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}

结果:

=====反序列化学生对象=======姓名:张三 年龄:23 性别:男 密码 : null姓名:李四 年龄:24 性别:女 密码 : null姓名:王五 年龄:25 性别:男 密码 : null姓名:赵六 年龄:26 性别:男 密码 : null=====反序列化集合对象=======姓名:张三 年龄:23 性别:男 密码 : null姓名:李四 年龄:24 性别:女 密码 : null姓名:王五 年龄:25 性别:男 密码 : null姓名:赵六 年龄:26 性别:男 密码 : null====反序列完成====

从结果中可以看到:password使用transient关键字后,没有被序列化,反序列化中,读出的是默认字段类型的默认值null

七、包含引用类型属性的对象序列化引用类必须也为可序列化

public class Teacher implements Serializable { private String name; // 姓名 private int age; // 年龄 private String gender; // 性别 private transient String password; // 密码属性不能被序列化 private Student stu; //这里的Student类必须也是可以序列化的,}

这里有个Teacher类,但属性中有一个Student类的对象,这时Teacher要实现序列时,Student必须也要实现Serializable接口才可以

7.1、序列化算法对象分配序列号当程序试图序列化一个对象时,将会检查是否已经被序列化,只有序列化后的对象才能被转换成字节序列输出如果对象已经被序列化,则程序直接输出一个序列化编号,而不在重新序列化7.2、序列化机制Teacher类:

package com.pb.serializable;import java.io.Serializable;/* * 教师类实例Serializable接口 */public class Teacher implements Serializable { private String name; // 姓名 private int age; // 年龄 private String gender; // 性别 private transient String password; // 密码属性不能被序列化 private Student stu; //这里的Student类必须也是可以序列化的, //构造方法 public Teacher() { //无参数 } public Teacher(String name, int age, String gender, String password, Student stu) { //有参数 this.name = name; this.age = age; this.gender = gender; this.password = password; this.stu = stu; } //getter、setter方法 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; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Student getStu() { return stu; } public void setStu(Student stu) { this.stu = stu; } // 自我介绍 public void say() { System.out.println("姓名:" + this.name + "\t年龄:" + this.age + "\t性别:" + this.gender+"\t密码 : "+this.password); } }

序列化和化序列化类:

package com.pb.serializable;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;/* * 老师类的序列化和反序列化 2个老师引用同一个学生对象 */public class WriterTeacherObj { public static void main(String[] args) { /* * 序列化 * 1.序列化时时候,会查找当前对象的序列化编号是否存在,不存在,保存该对象 * 2.写入操作时,当对象的序列化编号存在时候,会输出一个当前对象的序列化编号,而不是当前对象 * 3.反序列化对象时, 程序会自动查找,当前对象的序列化编号,之后如果,发现当前的对象的序列化编号被其它对象引用时,则返回同一个对象 */ try { //1.实例化ObjectOutputStream ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("d:/test/teacher.txt")); //2.实例化老师对象 Student student=new Student("马达", 23, "男", "123123"); //2个老师引用同一个学生对象 Teacher teacher_han=new Teacher("韩冰", 22, "女", "123456789", student); Teacher teacher_zhang=new Teacher("张三丰", 108, "男", "123456789", student); //3.对象序列 oos.writeObject(teacher_han); oos.writeObject(teacher_zhang); //4.关闭流 oos.close(); System.out.println("====================序列化完成================="); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } /* * 反序列化 */ System.out.println("==================开始反序列化================"); try { //1.实例化ObjectInputStream对象 ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/test/teacher.txt")); //2.反序列声明一个Teacher对象强制类型转换 Teacher teacher_han=(Teacher) ois.readObject(); Teacher teacher_zhang=(Teacher) ois.readObject(); //3.输入Teacher中的信息 System.out.println("==================老师信息================"); teacher_han.say(); teacher_zhang.say(); System.out.println("=================老师中学生信息============="); teacher_han.getStu().say(); teacher_zhang.getStu().say(); //4.关闭流 ois.close(); System.out.println("===========反序列化完成========="); //判断2个老师的学生是否为同一个 if(teacher_han.getStu()==teacher_zhang.getStu()){ System.out.println("张老师和韩老师教的是同一个学生"); }else{ System.out.println("张老师和韩老师教的不是同一个学生"); } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}

结果:

====================序列化完成===================================开始反序列化==================================老师信息================姓名:韩冰 年龄:22 性别:女 密码 : null姓名:张三丰 年龄:108 性别:男 密码 : null=================老师中学生信息=============姓名:马达 年龄:23 性别:男 密码 : null姓名:马达 年龄:23 性别:男 密码 : null===========反序列化完成=========张老师和韩老师教的是同一个学生

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航