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. 【ocp 052又加新题了】052新加的考试题及答案整理-第13题

    13.Which two are true about AWR snapshots? A) They are stored In the SYSAUX tablespace. B) They are ...

  2. php中的list()用法中要注意的地方

    php中list()函数是用数组对一列值进行赋值, 该函数只用于数字索引的数组,且假定数字索引从0开始.(这句话很重要,是从索引0开始为变量赋值,如果对应的数字索引不存在,则对应位的变量也为空值.) ...

  3. [ActionScript 3.0] 绘制扇形方法

    /** * 绘制扇形 * @param mc 承载扇形的对象 * @param x 圆心角x * @param y 圆心角y * @param r 半径 * @param angle 绘制角度 * @ ...

  4. nginx高性能WEB服务器系列之四配置文件详解

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

  5. XMPP Authentication

      From: http://www.ietf.org/rfc/rfc2831.txt 2 Authentication The following sections describe how to ...

  6. 海思hi35xx 开发学习(1):海思媒体处理平台架构

    处理平台架构图: 主要分为: 视频输入(VI):VI 模块捕获视频图像,可对其做剪切.去噪等处理,并输出多路不同分辨率的图像数据. 视频处理(VPSS):VPSS 模块接收 VI 和解码模块发送过来的 ...

  7. java中锁

    s锁的作用是就是保证线程安全,但是从另外成都讲影响了效率: 1 synchronized关键字 这个是虚拟机底层实现的, java中的关键字,内部实现为监视器锁,主要是通过对象监视器在对象头中的字段来 ...

  8. Log中关于start meeting在zVideoApp和zVideoUI中的流程可以搜索的几个字符串

    [31356:36164:04-29/17:53:38.164:INFO:SBConfUI.cpp(940)] CSBConfUI::OnConfStatusChanged(CONF_STATUS) ...

  9. Rstudio常用且不熟快捷键 “原版+中文” 整理

  10. Entity Framework添加记录时获取自增ID值

    与Entity Framework相伴的日子痛并快乐着.今天和大家分享一下一个快乐,两个痛苦. 先说快乐的吧.Entity Framework在将数据插入数据库时,如果主键字段是自增标识列,会将该自增 ...