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. CentOS7-Minimal1708安装设置python3

    使用 python -V 命令查看一下是否安装Python然后使用命令 which python 查看一下Python可执行文件的位置可见执行文件在/usr/bin/ 目录下,切换到该目录下执行 ll ...

  2. 条目二十四《当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择》

    条目二十四<当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择> 当效率至关重要时,应该在map::operator[]和map::insert之 ...

  3. Vue页面加载时,触发某个函数的方法

    需要在加载页面的时候调用生成验证码的click事件函数 解决方法如下,利用Vue中的mounted mounted:function(){ this.createcode();//需要触发的函数 } ...

  4. Tr A(矩阵快速幂)

    A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据.  每组数据的第一行有n(2 <= n < ...

  5. crontab例行性共作

    一.单一工作调度 at [-mldv] TIME at -c 工作号码 -m:当at工作结束后,即是没有输出信息,以email通知用户该工作已完成 -l:at -l相当于atq,列出目前系统上所有的a ...

  6. Delphi XE TStringBuilder

    function T_SunnySky_SDK.JoinItems(AParamDic: TDictionary<string, string>): string; var sb : TS ...

  7. SpringCloud---分布式配置中心---Spring Cloud Config

    1.概述 1.1 Spring Cloud Config是Spring Cloud的一个全新项目:   作用:为分布式系统中的基础设施.微服务应用提供集中化的外部配置支持:   分为服务端.客户端2个 ...

  8. 映射网络驱动器 net use

    net use z: \\10.1.1.1\Software 12345678 /user:admin net use z: /del 然后文件夹Software权限

  9. Java 网络通信相关

    http://m.blog.csdn.net/xiaojin21cen/article/details/78587541 越下面越底层 , 最后面的都是框架 , 下面的是 编程语言提供的库的 NIO ...

  10. 如何在vue中请求本地json文件

    1..修改webpack.base.conf.js 文件中添加'/static': resolve('static'),如下所示,此时存放于static的json文件就可以通过/static/xxx. ...