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_对象序列化、反序列化的更多相关文章

  1. java_对象序列化

    对象序列化(serializable) 序列化读:ObjectInputStream  ois=new ObjectInputStream(new FileInputStream("./gg ...

  2. Java对象序列化/反序列化的注意事项(转)

    Java对象序列化 对于一个存在Java虚拟机中的对象来说,其内部的状态只是保存在内存中.JVM退出之后,内存资源也就被释放,Java对象的内部状态也就丢失了.而在很多情况下,对象内部状态是需要被持久 ...

  3. Java对象序列化/反序列化的注意事项

    Java对象序列化 对于一个存在Java虚拟机中的对象来说,其内部的状态只是保存在内存中.JVM退出之后,内存资源也就被释放,Java对象的内部状态也就丢失了.而在很多情况下,对象内部状态是需要被持久 ...

  4. c# XML-Object对象 序列化-反序列化

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

  5. java 对象序列化与反序列化

    Java序列化与反序列化是什么? 为什么需要序列化与反序列化? 如何实现Java序列化与反序列化? 本文围绕这些问题进行了探讨. 1.Java序列化与反序列化  Java序列化是指把Java对象转换为 ...

  6. C#对象序列化与反序列化zz

      C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍........................ ...

  7. C#对象序列化与反序列化

    C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍.......................... ...

  8. Java Io 对象序列化和反序列化

    Java 支持将任何对象进行序列化操作,序列化后的对象文件便可通过流进行网络传输. 1.      对象序列化就是将对象转换成字节序列,反之叫对象的反序列化 2.      序列化流ObjectOut ...

  9. Json对象序列化与反序列化

    如果后台的参数数对象,需要在前台传入: JS代码: //创建JS对象 var CUTTING_TABLET_MO = new Object(); CUTTING_TABLET_MO.CUTTING_T ...

随机推荐

  1. redis 限制接口访问频率

    代码: <?php /** * */ class myRedis { private static $redis = null; /** * @return null|Redis */ publ ...

  2. 跑monkey前开启/关闭系统通知栏

    @echo off cls title 别忘了跑monkey啊 :menu cls color 0A echo. .禁用systemui并重启 echo. .启用systemui并重启 echo. e ...

  3. HDU6400-2018ACM暑假多校联合训练1004-Parentheses Matrix-构造

    Parentheses Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Oth ...

  4. Docker部署常见问题

    一.删除容器和镜像 在删除镜像之前要先用 docker rm 删掉依赖于这个镜像的所有容器(哪怕是已经停止的容器),否则无法删除该镜像. 停止容器 # docker stop $(docker ps ...

  5. java学习笔记_多态

    多态:父类的变量可以引用子类的对象 引用: Student s1 = stu; s1.setScore(200); 1.一个对象可以有多个引用,可以有多个变量操作同一个对象   2.当一个对象没有任何 ...

  6. nginx高性能WEB服务器系列之八--nginx日志分析与切割

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  7. 2016级算法第三次上机-F.ModricWang的导弹防御系统

    936 ModricWang的导弹防御系统 思路 题意即为:给出一个长度为n的序列,求出其最长不降子序列. 考虑比较平凡的DP做法: 令\(nums[i]\) 表示这个序列,\(f[x]\) 表示以第 ...

  8. 由import javax.persistence.*;引用引发问题的思考(SpringBoot)

    在学习SpringBoot的 JPA时候增加一个实体类的时候发现import包的时候一直报错. 对比一下,发现自己的项目里面是少了 spring-boot-starter-data-jpa.jar包的 ...

  9. Luogu - P3384 树链剖分 [挂模板专用]

    题意:请码个树剖模板支持子树区间加/查询和路径加/查询 纯练手 盲敲技能++ 以后网络赛复制模板速度++++ 对链操作时注意方向 #include<bits/stdc++.h> #defi ...

  10. git 换行符替换

    https://help.github.com/en/articles/dealing-with-line-endings rm .git/index git reset https://github ...