java中对象反序列化怎空文件_java_对象序列化、反序列化

1.概念

序列化:将对象转化为字节序列的过程

反序列化:将字节序列转化为对象的过程

用途:

A:将对象转化为字节序列保存在硬盘上,如文件中,如文本中的例子就是将person对象序列化成字节序列,存在person.txt文件中

B:网络传输中一般都是以对象序列化的形式存在,在网络的发送/接收两端进行对象的序列化/反序列化

输入/输出的使用:

一般都是针对内存而言,内存--硬盘--》outputStream     从硬盘--内存--》inputStream

具体使用要根据场景来确定

2.Serializable-example

2.1 无显式的指定UID,采用编译系统自动生成的

Object:

packagecom.java.baseinfo.knowledge.code.serializable;importjava.io.Serializable;

public class Person implementsSerializable {private intage;privateString name;privateString sex;public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicString getSex() {returnsex;

}public voidsetSex(String sex) {this.sex =sex;

}

@OverridepublicString toString() {final StringBuffer sb = new StringBuffer("Person{");

sb.append("age=").append(age);

sb.append(", name='").append(name).append('\'');

sb.append(", sex='").append(sex).append('\'');

sb.append('}');returnsb.toString();

}

}

object  uid

packagecom.java.baseinfo.knowledge.code.serializable;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;

public classTestObjSerializeAndDeserialize {public static voidmain(String[] args) {//序列化

SerializablePerson();//反序列化//Deserialization();

}private static voidSerializablePerson() {

Person person= newPerson();

person.setAge(10);

person.setName("测试");

person.setSex("女");

String path= "src/test/resources/person.txt";try{

FileOutputStream fileOutputStream= new FileOutputStream(newFile(path));

ObjectOutputStream objectOutputStream= newObjectOutputStream(fileOutputStream);

objectOutputStream.writeObject(person);

System.out.println("序列化成功");

fileOutputStream.close();

objectOutputStream.close();

}catch(FileNotFoundException e) {

System.out.printf("FileNotFoundException====>" +e);

}catch(IOException e) {

System.out.printf("IOException====>" +e);

}

}private staticPerson Deserialization() {try{

FileInputStream fileInputStream= new FileInputStream(new File("src/test/resources/person.txt"));

ObjectInputStream objectInputStream= newObjectInputStream(fileInputStream);

Person person=(Person) objectInputStream.readObject();

System.out.printf("Deserialization.person===>"+person);

}catch(FileNotFoundException e) {

System.out.printf("FileNotFoundException====>" +e);

}catch(IOException e) {

System.out.printf("IOException====>" +e);

}catch(ClassNotFoundException e) {

System.out.printf("ClassNotFoundException====>" +e);

}return null;

}

}

先序列化,才进行反序列化

Deserialization.person===>Person{age=10, name='测试', sex='女'}

给person增加字段,再用原来的序列化后的结果,进行反序列化;

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Serializable;

public class Person implements Serializable {

private int age;

private String name;

private String sex;

// 增加字段测试序列化

private String addText;

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public String getAddText() {

return addText;

}

public void setAddText(String addText) {

this.addText = addText;

}

@Override

public String toString() {

final StringBuffer sb = new StringBuffer("Person{");

sb.append("age=").append(age);

sb.append(", name='").append(name).append('\'');

sb.append(", sex='").append(sex).append('\'');

sb.append(", addText='").append(addText).append('\'');

sb.append('}');

return sb.toString();

}

}

运行结果

IOException====>java.io.InvalidClassException: com.java.baseinfo.knowledge.code.serializable.Person; local class incompatible: stream classdesc serialVersionUID = 6964452789008335213, local class serialVersionUID = -3534890433624150186

Process finished with exit code 0

原因是:之前代码中未显示的指定UID,当Object中新增字段时,编译器又新生成一个UID,于是出现序列化版本不一致的问题;

2.2 显式指定UID

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Serializable;

public class Person implements Serializable {

private static final long serialVersionUID = -3534890433624150186L;

private int age;

private String name;

private String sex;

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

@Override

public String toString() {

final StringBuffer sb = new StringBuffer("Person{");

sb.append("age=").append(age);

sb.append(", name='").append(name).append('\'');

sb.append(", sex='").append(sex).append('\'');

sb.append('}');

return sb.toString();

}

}

运行上述main函数, 先进行序列化,然后再对object增加属性,再序列化的结果,进行反序列化

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Serializable;

public class Person implements Serializable {

private static final long serialVersionUID = -3534890433624150186L;

private int age;

private String name;

private String sex;

// 增加字段测试序列化

private String addText;

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public String getAddText() {

return addText;

}

public void setAddText(String addText) {

this.addText = addText;

}

@Override

public String toString() {

final StringBuffer sb = new StringBuffer("Person{");

sb.append("age=").append(age);

sb.append(", name='").append(name).append('\'');

sb.append(", sex='").append(sex).append('\'');

sb.append(", addText='").append(addText).append('\'');

sb.append('}');

return sb.toString();

}

}

反序列化结果,新增的字段为空值

Deserialization.person===>Person{age=10, name='测试', sex='女', addText='null'}

Process finished with exit code 0

显式的指定UID,目前常用到的场景是:当object增加的字段时候,不希望反序列化出现异常,即希望类的不同版本对序列化兼容;

等用到其他场景的时候,再更新。。

3. Externalizable-example

import java.io.Externalizable;

import java.io.IOException;

import java.io.ObjectInput;

import java.io.ObjectOutput;

public class PersonExternal implements Externalizable {

private int age;

private String name;

private String sex;

@Override

public void writeExternal(ObjectOutput out) throws IOException {

//未实现

}

@Override

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

//未实现

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

@Override

public String toString() {

final StringBuffer sb = new StringBuffer("PersonExternal{");

sb.append("age=").append(age);

sb.append(", name='").append(name).append('\'');

sb.append(", sex='").append(sex).append('\'');

sb.append('}');

return sb.toString();

}

先序列化再反序列化

package com.java.baseinfo.knowledge.code.serializable;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

public class TetsExternalizable {

public static void main(String[] args) {

//ExternalizableEnCode();

ExternalizableDecode();

}

private static void ExternalizableEnCode() {

PersonExternal personExternal = new PersonExternal();

personExternal.setName("测试");

personExternal.setAge(18);

personExternal.setSex("女");

File file = new File("src/test/resources/personExternal.txt");

try {

FileOutputStream fileOutputStream = new FileOutputStream(file);

ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);

outputStream.writeObject(personExternal);

System.out.printf("ExternalizableEnCode===>序列化完成");

} catch (FileNotFoundException e) {

System.out.printf("ExternalizableEnCode.FileNotFoundException===>" + e);

} catch (IOException e) {

System.out.printf("ExternalizableEnCode.IOException===>" + e);

}

}

private static void ExternalizableDecode() {

try {

File file = new File("src/test/resources/personExternal.txt");

FileInputStream fileInputStream = new FileInputStream(file);

ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);

PersonExternal personExternal = (PersonExternal) inputStream.readObject();

System.out.println("ExternalizableDecode.personExternal====>" + personExternal);

} catch (FileNotFoundException e) {

System.out.printf("ExternalizableDecode.FileNotFoundException===>" + e);

} catch (IOException e) {

System.out.printf("ExternalizableDecode.IOException===>" + e);

} catch (ClassNotFoundException e) {

System.out.printf("ExternalizableDecode.ClassNotFoundException===>" + e);

}

}

}

运行结果

ExternalizableDecode.personExternal====>PersonExternal{age=0, name='null', sex='null'}

此时发现,当时序列化的对象值并未持久化,是因为我们没有重写Externalizable的writeExternal和readExternal方法

重写externalizable方法

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Externalizable;

import java.io.IOException;

import java.io.ObjectInput;

import java.io.ObjectOutput;

public class PersonExternal implements Externalizable {

private int age;

private String name;

private String sex;

@Override

public void writeExternal(ObjectOutput out) throws IOException {

out.writeInt(age);

out.writeObject(name);

out.writeObject(sex);

}

@Override

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

age = in.readInt();

name = (String) in.readObject();

sex = (String) in.readObject();

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

@Override

public String toString() {

final StringBuffer sb = new StringBuffer("PersonExternal{");

sb.append("age=").append(age);

sb.append(", name='").append(name).append('\'');

sb.append(", sex='").append(sex).append('\'');

sb.append('}');

return sb.toString();

}

}

运行结果

ExternalizableEnCode===>序列化完成ExternalizableDecode.personExternal====>PersonExternal{age=18, name='测试', sex='女'}

结论:

Externalizable反序列化的时候,会调用被序列化的无参构造函数去创建一个新的对象,然后再将被保存的对象的字段分别填充到新的对象中;所以使用Externalizable时候,除了重写write/read方法外,所需要序列化的对象还需要提供一个无参的构造函数;若没有无参构造函数,则会抛异常:java.io.InvalidClassException

eg:

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Externalizable;

import java.io.IOException;

import java.io.ObjectInput;

import java.io.ObjectOutput;

public class PersonExternal implements Externalizable {

private int age;

private String name;

private String sex;

//构造函数

public PersonExternal(int age, String name, String sex) {

this.age = age;

this.name = name;

this.sex = sex;

}

@Override

public void writeExternal(ObjectOutput out) throws IOException {

out.writeInt(age);

out.writeObject(name);

out.writeObject(sex);

}

@Override

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

age = in.readInt();

name = (String) in.readObject();

sex = (String) in.readObject();

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

@Override

public String toString() {

final StringBuffer sb = new StringBuffer("PersonExternal{");

sb.append("age=").append(age);

sb.append(", name='").append(name).append('\'');

sb.append(", sex='").append(sex).append('\'');

sb.append('}');

return sb.toString();

}

}

test main

package com.java.baseinfo.knowledge.code.serializable;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

public class TetsExternalizable {

public static void main(String[] args) {

ExternalizableEnCode();

ExternalizableDecode();

}

private static void ExternalizableEnCode() {

PersonExternal personExternal = new PersonExternal(18,"测试","女");

/* personExternal.setName("测试");

personExternal.setAge(18);

personExternal.setSex("女");*/

File file = new File("src/test/resources/personExternal.txt");

try {

FileOutputStream fileOutputStream = new FileOutputStream(file);

ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);

outputStream.writeObject(personExternal);

System.out.printf("ExternalizableEnCode===>序列化完成");

} catch (FileNotFoundException e) {

System.out.printf("ExternalizableEnCode.FileNotFoundException===>" + e);

} catch (IOException e) {

System.out.printf("ExternalizableEnCode.IOException===>" + e);

}

}

private static void ExternalizableDecode() {

try {

File file = new File("src/test/resources/personExternal.txt");

FileInputStream fileInputStream = new FileInputStream(file);

ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);

PersonExternal personExternal = (PersonExternal) inputStream.readObject();

System.out.println("ExternalizableDecode.personExternal====>" + personExternal);

} catch (FileNotFoundException e) {

System.out.printf("ExternalizableDecode.FileNotFoundException===>" + e);

} catch (IOException e) {

System.out.printf("ExternalizableDecode.IOException===>" + e);

} catch (ClassNotFoundException e) {

System.out.printf("ExternalizableDecode.ClassNotFoundException===>" + e);

}

}

}

运行结果

ExternalizableEnCode===>序列化完成ExternalizableDecode.IOException===>java.io.InvalidClassException: com.java.baseinfo.knowledge.code.serializable.PersonExternal; no valid constructor

4.transient 关键字

如果对象的属性被赋予transient属性,则该对象在序列化的时候,当前字段不会被序列化;那么再反序列化的时候,该字段会被赋予默认值,如int类型会是0,String为null

eg

public class Person implements Serializable {

private static final long serialVersionUID = -3534890433624150186L;

private transient int age;

private transient String name;

private String sex;

// 增加字段测试序列化

private String addText;

运行2中的序列化代码,则结果为

序列化成功

反序列化Deserialization.person===>Person{age=0, name='null', sex='女', addText='addText'}

Process finished with exit code 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值