java反序列化对象,【Java】Java对象的序列化和反序列化

对象序列化

对象序列化机制允许把内存中的Java对象转换成与平台无关的二进制流,从而可以保存到磁盘或者进行网络传输,其它程序获得这个二进制流后可以将其恢复成原来的Java对象。 序列化机制可以使对象可以脱离程序的运行而对立存在

序列化的含义和意义

序列化

序列化机制可以使对象可以脱离程序的运行而对立存在

序列化(Serialize)指将一个java对象写入IO流中,与此对应的是,对象的反序列化(Deserialize)则指从IO流中恢复该java对象

如果需要让某个对象可以支持序列化机制,必须让它的类是可序列化(serializable),为了让某个类可序列化的,必须实现如下两个接口之一:

Serializable:标记接口,实现该接口无须实现任何方法,只是表明该类的实例是可序列化的

Externalizable

所有在网络上传输的对象都应该是可序列化的,否则将会出现异常;所有需要保存到磁盘里的对象的类都必须可序列化;程序创建的每个JavaBean类都实现Serializable;

类自定义序列化方式一:实现Serializable接口

序列化

示例代码

1 /**

2 * ObjectInputStream和OjbectOutputSteam3 * 用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可4 * 以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。5 */

6 public classObjectInputOutputStreamTest {7 public static voidmain(String[] args) {8 ObjectInputOutputStreamTest test = newObjectInputOutputStreamTest();9 test.testObjectOutputStream();10 }11

12 /**

13 * 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制14 */

15 public voidtestObjectOutputStream(){16 ObjectOutputStream oos = null;17 try{18 oos = new ObjectOutputStream(new FileOutputStream("object.bat"));19 oos.writeObject(new Person(12, "小白"));20 oos.flush();21 } catch(IOException e) {22 e.printStackTrace();23 } finally{24 if(oos != null) {25 try{26 oos.close();27 } catch(IOException e) {28 e.printStackTrace();29 }30 }31 }32 }33

34 }35

36

37 class Person implementsSerializable{38

39 public static final long serialVersionUID = 123321;40

41 Integer age;42 String name;43

44 publicPerson(Integer age, String name) {45 this.age =age;46 this.name =name;47 }48

49 @Override50 publicString toString() {51 return "Person{" +

52 "age=" + age +

53 ", name=‘" + name + ‘\‘‘ +

54 ‘}‘;55 }56 }

反序列化

从二进制流中恢复Java对象,则需要使用反序列化,程序可以通过如下两个步骤来序列化该对象:

示例代码

1 /**

2 * 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制3 */

4 public voidtestObjectInputStream(){5 ObjectInputStream ois = null;6 try{7 ois = new ObjectInputStream(new FileInputStream("object.bat"));8 Person p =(Person) ois.readObject();9 System.out.println(p);10 } catch(IOException e) {11 e.printStackTrace();12 } catch(ClassNotFoundException e) {13 e.printStackTrace();14 } finally{15 if(ois != null) {16 try{17 ois.close();18 } catch(IOException e) {19 e.printStackTrace();20 }21 }22 }23 }

反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化恢复Java对象时,必须提供Java对象所属的class文件,否则会引发ClassNotFoundException异常;反序列化机制无须通过构造器来初始化Java对象

如果使用序列化机制向文件中写入了多个Java对象,使用反序列化机制恢复对象必须按照实际写入的顺序读取。当一个可序列化类有多个父类时(包括直接父类和间接父类),这些父类要么有无参的构造器,要么也是可序列化的—否则反序列化将抛出InvalidClassException异常。如果父类是不可序列化的,只是带有无参数的构造器,则该父类定义的Field值不会被序列化到二进制流中

对象引用的序列化

如果某个类的Field类型不是基本类型或者String类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则有用该类型的Field的类也是不可序列化的

serialVersionUID

1、凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:

?  private static final long serialVersionUID;

?  serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象 进行版本控制,有关各版本反序列化时是否兼容。

?  如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自 动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议, 显式声明。

? 2、简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验 证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的 serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同 就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异 常。(InvalidCastException)

Java序列化的特殊情况

1:静态变量和transient关键字修饰的变量不能被序列化;

2:反序列化时要按照序列化的顺序重构对象:如先序列化A后序列化B,则反序列化时也要先获取A后获取B,否则报错。

3:序列化ID的作用:虚拟机是否允许对象反序列化,不仅取决于该对象所属类路径和功能代码是否与虚拟机加载的类一致,而是主要取决于对象所属类与虚拟机加载的该类的序列化 ID 是否一致。

4:自定义序列化方法的应用场景:对某些敏感数据进行加密操作后再序列化;反序列化对加密数据进行解密操作。

5:重复序列化:同一个对象重复序列化时,不会把对象内容再次序列化,而是新增一个引用指向第一次序列化时的对象而已。

类自定义序列化方式二:实现Externalnalizable接口

实现Externalnalizable接口(继承自 Serializable接口),并且在类中实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,在方法中定义类对象自定义的序列化和反序列化操作。这样通过对象输出流和对象输入流的输入输出方法序列化和反序列化对象时会自动调用类中定义的readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法。

void readExternal(ObjectInput in):需要序列化的类实现readExternal()方法来实现反序列化。该方法调用DataInput(它是ObjectInput的父接口)的方法来恢复基本类型的实例变量值,调用ObjectInput的readObject()方法来恢复引用类型的实例变量值

void writeExternal(Object out):需要序列化的类实现该方法来保存对象的状态。该方法调用DataOutput(它是ObjectOutput的父接口)的方法来保存基本类型的实例变量值,调用ObjectOutput的writeObject()方法来保存引用类型的实例变量值

示例代码

2b65ef29a5872cc0e4771c25889edd04.gif

6a087676c59fa8b19d76e6bb55a32902.gif

1 public classObjectInputOutputStreamTest {2 public static voidmain(String[] args) {3 ObjectInputOutputStreamTest test = newObjectInputOutputStreamTest();4 test.testAnimal();5 }6

7

8 public voidtestAnimal(){9 ObjectOutputStream oos = null;10 try{11 oos = new ObjectOutputStream(new FileOutputStream("object2.bat"));12 oos.writeObject(new Animal(12, "小白"));13 oos.flush();14 } catch(IOException e) {15 e.printStackTrace();16 } finally{17 if(oos != null) {18 try{19 oos.close();20 } catch(IOException e) {21 e.printStackTrace();22 }23 }24 }25

26

27 ObjectInputStream ois = null;28 try{29 ois = new ObjectInputStream(new FileInputStream("object2.bat"));30 Animal a =(Animal) ois.readObject();31 System.out.println(a);32 } catch(IOException e) {33 e.printStackTrace();34 } catch(ClassNotFoundException e) {35 e.printStackTrace();36 } finally{37 if(ois != null) {38 try{39 ois.close();40 } catch(IOException e) {41 e.printStackTrace();42 }43 }44 }45 }46 }47

48

49

50 class Animal implementsExternalizable{51

52 public static final long serialVersionUID = 12345;53

54 Integer age;55 String name;56

57 publicAnimal() {58 }59

60 publicAnimal(Integer age, String name) {61 this.age =age;62 this.name =name;63 }64

65 public void writeExternal(ObjectOutput out) throwsIOException {66 out.writeInt(age);67 out.writeUTF(name);68 }69

70 public void readExternal(ObjectInput in) throwsIOException, ClassNotFoundException {71 age =in.readInt();72 name =in.readUTF();73 }74

75

76 @Override77 publicString toString() {78 return "Animal{" +

79 "age=" + age +

80 ", name=‘" + name + ‘\‘‘ +

81 ‘}‘;82 }83 }

View Code

f1ebe3e366647339a052c1eba2aac16c.png

其他序列化手段

1:把对象包装成JSON格式进行序列化

2:用XML格式序列化

3:采用第三方插件(如:ProtoBuf)进行序列化

原文:https://www.cnblogs.com/h--d/p/14163810.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值