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 ...
随机推荐
- redis 限制接口访问频率
代码: <?php /** * */ class myRedis { private static $redis = null; /** * @return null|Redis */ publ ...
- 跑monkey前开启/关闭系统通知栏
@echo off cls title 别忘了跑monkey啊 :menu cls color 0A echo. .禁用systemui并重启 echo. .启用systemui并重启 echo. e ...
- HDU6400-2018ACM暑假多校联合训练1004-Parentheses Matrix-构造
Parentheses Matrix Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Oth ...
- Docker部署常见问题
一.删除容器和镜像 在删除镜像之前要先用 docker rm 删掉依赖于这个镜像的所有容器(哪怕是已经停止的容器),否则无法删除该镜像. 停止容器 # docker stop $(docker ps ...
- java学习笔记_多态
多态:父类的变量可以引用子类的对象 引用: Student s1 = stu; s1.setScore(200); 1.一个对象可以有多个引用,可以有多个变量操作同一个对象 2.当一个对象没有任何 ...
- nginx高性能WEB服务器系列之八--nginx日志分析与切割
nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...
- 2016级算法第三次上机-F.ModricWang的导弹防御系统
936 ModricWang的导弹防御系统 思路 题意即为:给出一个长度为n的序列,求出其最长不降子序列. 考虑比较平凡的DP做法: 令\(nums[i]\) 表示这个序列,\(f[x]\) 表示以第 ...
- 由import javax.persistence.*;引用引发问题的思考(SpringBoot)
在学习SpringBoot的 JPA时候增加一个实体类的时候发现import包的时候一直报错. 对比一下,发现自己的项目里面是少了 spring-boot-starter-data-jpa.jar包的 ...
- Luogu - P3384 树链剖分 [挂模板专用]
题意:请码个树剖模板支持子树区间加/查询和路径加/查询 纯练手 盲敲技能++ 以后网络赛复制模板速度++++ 对链操作时注意方向 #include<bits/stdc++.h> #defi ...
- git 换行符替换
https://help.github.com/en/articles/dealing-with-line-endings rm .git/index git reset https://github ...