java_对象序列化、反序列化
1.概念
序列化:将对象转化为字节序列的过程
反序列化:将字节序列转化为对象的过程
用途:
A:将对象转化为字节序列保存在硬盘上,如文件中,如文本中的例子就是将person对象序列化成字节序列,存在person.txt文件中
B:网络传输中一般都是以对象序列化的形式存在,在网络的发送/接收两端进行对象的序列化/反序列化
输入/输出的使用:
一般都是针对内存而言,内存--硬盘--》outputStream 从硬盘--内存--》inputStream
具体使用要根据场景来确定
2.Serializable-example
2.1 无显式的指定UID,采用编译系统自动生成的
Object:
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; 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();
}
}
object uid
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 TestObjSerializeAndDeserialize { public static void main(String[] args) {
// 序列化
SerializablePerson();
// 反序列化
//Deserialization();
} private static void SerializablePerson() {
Person person = new Person();
person.setAge(10);
person.setName("测试");
person.setSex("女"); String path = "src/test/resources/person.txt"; try {
FileOutputStream fileOutputStream = new FileOutputStream(new File(path)); ObjectOutputStream objectOutputStream = new ObjectOutputStream(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 static Person Deserialization() { try {
FileInputStream fileInputStream = new FileInputStream(new File("src/test/resources/person.txt")); ObjectInputStream objectInputStream = new ObjectInputStream(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
参考:https://www.cnblogs.com/xdp-gacl/p/3777987.html
http://www.importnew.com/17964.html
java_对象序列化、反序列化的更多相关文章
- java_对象序列化
对象序列化(serializable) 序列化读:ObjectInputStream ois=new ObjectInputStream(new FileInputStream("./gg ...
- Java对象序列化/反序列化的注意事项(转)
Java对象序列化 对于一个存在Java虚拟机中的对象来说,其内部的状态只是保存在内存中.JVM退出之后,内存资源也就被释放,Java对象的内部状态也就丢失了.而在很多情况下,对象内部状态是需要被持久 ...
- Java对象序列化/反序列化的注意事项
Java对象序列化 对于一个存在Java虚拟机中的对象来说,其内部的状态只是保存在内存中.JVM退出之后,内存资源也就被释放,Java对象的内部状态也就丢失了.而在很多情况下,对象内部状态是需要被持久 ...
- c# XML-Object对象 序列化-反序列化
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...
- java 对象序列化与反序列化
Java序列化与反序列化是什么? 为什么需要序列化与反序列化? 如何实现Java序列化与反序列化? 本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为 ...
- C#对象序列化与反序列化zz
C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍........................ ...
- C#对象序列化与反序列化
C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍.......................... ...
- Java Io 对象序列化和反序列化
Java 支持将任何对象进行序列化操作,序列化后的对象文件便可通过流进行网络传输. 1. 对象序列化就是将对象转换成字节序列,反之叫对象的反序列化 2. 序列化流ObjectOut ...
- Json对象序列化与反序列化
如果后台的参数数对象,需要在前台传入: JS代码: //创建JS对象 var CUTTING_TABLET_MO = new Object(); CUTTING_TABLET_MO.CUTTING_T ...
随机推荐
- CentOS7-Minimal1708安装设置python3
使用 python -V 命令查看一下是否安装Python然后使用命令 which python 查看一下Python可执行文件的位置可见执行文件在/usr/bin/ 目录下,切换到该目录下执行 ll ...
- 条目二十四《当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择》
条目二十四<当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择> 当效率至关重要时,应该在map::operator[]和map::insert之 ...
- Vue页面加载时,触发某个函数的方法
需要在加载页面的时候调用生成验证码的click事件函数 解决方法如下,利用Vue中的mounted mounted:function(){ this.createcode();//需要触发的函数 } ...
- Tr A(矩阵快速幂)
A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据. 每组数据的第一行有n(2 <= n < ...
- crontab例行性共作
一.单一工作调度 at [-mldv] TIME at -c 工作号码 -m:当at工作结束后,即是没有输出信息,以email通知用户该工作已完成 -l:at -l相当于atq,列出目前系统上所有的a ...
- Delphi XE TStringBuilder
function T_SunnySky_SDK.JoinItems(AParamDic: TDictionary<string, string>): string; var sb : TS ...
- SpringCloud---分布式配置中心---Spring Cloud Config
1.概述 1.1 Spring Cloud Config是Spring Cloud的一个全新项目: 作用:为分布式系统中的基础设施.微服务应用提供集中化的外部配置支持: 分为服务端.客户端2个 ...
- 映射网络驱动器 net use
net use z: \\10.1.1.1\Software 12345678 /user:admin net use z: /del 然后文件夹Software权限
- Java 网络通信相关
http://m.blog.csdn.net/xiaojin21cen/article/details/78587541 越下面越底层 , 最后面的都是框架 , 下面的是 编程语言提供的库的 NIO ...
- 如何在vue中请求本地json文件
1..修改webpack.base.conf.js 文件中添加'/static': resolve('static'),如下所示,此时存放于static的json文件就可以通过/static/xxx. ...