什么是序列化和反序列化

序列化:可以将对象转化成一个字节序列,便于存储。
反序列化:将序列化的字节序列还原。
优点:可以实现对象的”持久性”, 所谓持久性就是指对象的生命周期不取决于程序。

序列化方式1: 实现Serializable接口(隐式序列化)

通过实现Serializable接口,这种是隐式序列化(不需要手动),这种是最简单的序列化方式,会自动序列化所有非static和 transient关键字修饰的成员变量。
代码示例

class Student implements Serializable{private String name;private int age;public static int QQ = 1234;private transient String address = "CHINA";Student(String name, int age ){this.name = name;this.age = age;}public String toString() {return "name: " + name + "\n"+"age: " + age + "\n"+"QQ: " + QQ + "\n"+ "address: " + address;}public void SetAge(int age) {this.age = age;}
}public class SerializableDemo {public static void main(String[] args) throws IOException,
ClassNotFoundException {//创建可序列化对象System.out.println("原来的对象:");Student stu = new Student("Ming", 16);System.out.println(stu);//创建序列化输出流ByteArrayOutputStream buff = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(buff);//将序列化对象存入缓冲区out.writeObject(stu);//修改相关值Student.QQ = 6666; // 发现打印结果QQ的值被改变stu.SetAge(18);  //发现值没有被改变//从缓冲区取回被序列化的对象ObjectInputStream in = new ObjectInputStream(newByteArrayInputStream(buff.toByteArray()));Student newStu = (Student) in.readObject();System.out.println("序列化后取出的对象:");System.out.println(newStu);}
}

打印的结果是:
原来的对象:name: Ming age: 16 QQ: 1234
address: CHINA
序列化后取出的对象:
name: Ming age: 16 QQ: 6666 address: null

发现address(被transient)和QQ(被static)也没有被序列化,中途修改QQ的值是为了以防误会QQ被序列化了。因为序列化可以保存对象的状态,但是QQ的值被改变了,说明没有被序列化。static成员不属于对象实例,可能被别的对象修改没办法序列化,序列化是序列对象。对于address被反序列化后由于没有对应的引用,所以为null。而且Serializable不会调用构造方法。
PS:细心的可能发现序列化很诱人,可以保存对象的初始信息,在以后可以回到这个初始状态

序列化方式2:实现Externalizable接口(显式序列化)

实现Externalizable接口继承自Serializable, 我们在实现该接口时,必须实现writeExternal()和readExternal()方法,而且只能通过手动进行序列化,并且两个方法是自动调用的,因此,这个序列化过程是可控的,可以自己选择哪些部分序列化
代码示例:

public class Blip implements Externalizable{private int i ;private String s;public Blip() {}public Blip(String x, int a) {System.out.println("Blip (String x, int a)");s = x;i = a;}public String toString() {return s+i;}@Overridepublic void writeExternal(ObjectOutput out) throws IOException {// TODO Auto-generated method stubSystem.out.println("Blip.writeExternal");out.writeObject(s);out.writeInt(i);}@Overridepublic void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {// TODO Auto-generated method stubSystem.out.println("Blip.readExternal");s = (String)in.readObject();i = in.readInt();}public static void main(String[] args) throws FileNotFoundException,IOException, ClassNotFoundException {System.out.println("Constructing objects");Blip b = new Blip("A Stirng", 47);System.out.println(b);ObjectOutputStream o = new ObjectOutputStream(newFileOutputStream("F://Demo//file1.txt"));System.out.println("保存对象");o.writeObject(b);o.close();//获得对象System.out.println("获取对象");ObjectInputStream in = new ObjectInputStream(newFileInputStream("F://Demo//file1.txt"));System.out.println("Recovering b");b = (Blip)in.readObject();System.out.println(b);}
}

打印的结果是:
Constructing objects
Blip (String x, int a)
A Stirng47
保存对象:
Blip.writeExternal
获取对象:
Recovering b
Blip.readExternal
A Stirng47
当注释掉writeExternal和readExternal方法后打印结果为:
Constructing objects Blip (String x, int a) A Stirng47 保存对象
Blip.writeExternal 获取对象 Recovering b Blip.readExternal null0
这说明:Externalizable类会调用public的构造函数先初始化对象,在调用所保存的内容将对象还原。假如构造方法不是public则会出现运行时错误

序列化方式3:实现Serializable接口+添加writeObject()和readObject()方法。(显+隐序列化)

如果想将方式1和方式2的优点都用到的话,可以采用方式3, 先实现Serializable接口,并且添加writeObject()和readObject()方法。注意这里是添加,不是重写或者覆盖。但是添加的这两个方法必须有相应的格式。
1. 方法必须要被private修饰 —–>才能被调用
2. 第一行调用默认的defaultRead/WriteObject() —–>隐式序列化非static和transient
3. 调用read/writeObject()将获得的值赋给相应的值 —–>显式序列化
代码示例:

public class SerDemo implements Serializable{public transient int age = 23;public String name ;public SerDemo(){System.out.println("默认构造器。。。");
}public SerDemo(String name) {this.name = name;
}private  void writeObject(ObjectOutputStream stream) throws IOException {stream.defaultWriteObject();stream.writeInt(age);
}private void readObject(ObjectInputStream stream) throws
ClassNotFoundException, IOException {stream.defaultReadObject();age = stream.readInt();
}public String toString() {return "年龄" + age + " " + name;
}public static void main(String[] args) throws IOException,
ClassNotFoundException {SerDemo stu = new SerDemo("Ming");ByteArrayOutputStream bout = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(bout);out.writeObject(stu);ObjectInputStream in = new ObjectInputStream(newByteArrayInputStream(bout.toByteArray()));SerDemo stu1 = (SerDemo) in.readObject();System.out.println(stu1);}
}

打印结果为:年龄23 Ming
注释掉stream.writeInt(age)和age= stream.readInt()后:年龄0 Ming
方式3结合了显式和隐式序列化,Ming被正常序列化,由于age被trancient修饰,所以需要显式序列化

最后再说一下 Json序列化

Json序列化一般会使用jackson包,通过ObjectMapper类来进行一些操作,比如将对象转化为byte数组或者将json串转化为对象。现在的大多数公司都将json作为服务器端返回的数据格式。比如调用一个服务器接口,通常的请求为:xxx.json?a=xxx&b=xxx的形式
接着上个例子:

package serialize;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;public class JsonSerialize {public static void main(String[] args) throws IOException {new JsonSerialize().start();}public void start() throws IOException {User u = new User();List<User> friends = new ArrayList<>();u.setUserName("张三");u.setPassWord("123456");u.setUserInfo("张三是一个很牛逼的人");u.setFriends(friends);User f1 = new User();f1.setUserName("李四");f1.setPassWord("123456");f1.setUserInfo("李四是一个很牛逼的人");User f2 = new User();f2.setUserName("王五");f2.setPassWord("123456");f2.setUserInfo("王五是一个很牛逼的人");friends.add(f1);friends.add(f2);ObjectMapper mapper = new ObjectMapper();Long t1 = System.currentTimeMillis();byte[] writeValueAsBytes = null;for (int i = 0; i < 10; i++) {writeValueAsBytes = mapper.writeValueAsBytes(u);
}System.out.println("json serialize: " + (System.currentTimeMillis() -
t1) + "ms; 总大小:" + writeValueAsBytes.length);Long t2 = System.currentTimeMillis();User user = mapper.readValue(writeValueAsBytes, User.class);System.out.println("json deserialize: " + (System.currentTimeMillis() -
t2) + "ms; User: " + user);}
}

运行结果:
json serialize: 55ms; 总大小:341 json deserialize: 35ms;
User: User [userId=null, userName=张三, passWord=123456, userInfo=张三是一个很牛逼的人,
friends=[User [userId=null, userName=李四, passWord=123456, userInfo=李四是一个很牛逼的人, friends=null], User [userId=null, userName=王五, passWord=123456,
userInfo=王五是一个很牛逼的人, friends=null]]]

Java序列化的3种方式相关推荐

  1. [转载] Java序列化的几种方式以及序列化的作用

    参考链接: Java中带有继承的对象序列化 文章转载自:  本文着重讲解一下Java序列化的相关内容. 如果对Java序列化感兴趣的同学可以研究一下. 一.Java序列化的作用 有的时候我们想要把一个 ...

  2. Java序列化的几种方式以及序列化的作用(文章有所改变)

    本文着重讲解一下Java序列化的相关内容. 如果对Java序列化感兴趣的同学可以研究一下. 一.Java序列化的作用    有的时候我们想要把一个Java对象变成字节流的形式传出去,有的时候我们想要从 ...

  3. Java序列化的几种方式

    概念 序列化:可以将对象转化成一个字节序列,便于存储. 反序列化:将序列化的字节序列还原 优点:可以实现对象的"持久性", 所谓持久性就是指对象的生命周期不取决于程序 原生序列化方 ...

  4. 简述Java序列化的几种方式

    目录 JDK原生的序列化 字符串获取字节流 Protobuf Protostuff Thrift kryo hessian fst JSON字符串序列化 Jackson Gson FastJson 序 ...

  5. java创建对象的五种方式

    java创建对象的五种方式 一.使用new关键字 二.使用clone方法 三.使用反序列化 四.使用反射 五.使用Unsafe 一.使用new关键字 如 User user=new User(); 执 ...

  6. Java 创建对象的 6 种方式,总有一种适合你

    创建对象的 6 种方式 假设有个女朋友类: @Data @NoArgsConstructor @AllArgsConstructor class GirlFriend {private String ...

  7. Java技术分享:升级所安装Java版本的两种方式

    在进行Java开发的时候我们可能会需要升级所安装的Java版本,那么你知道应该如何安装吗?小千今天就来给大家介绍两种方式. 一.卸载掉原本安装的Java,下载最新安装包安装即可. 这个步骤就不介绍了, ...

  8. Java操作Excel三种方式POI、Hutool、EasyExcel

    Java操作Excel三种方式POI.Hutool.EasyExcel 1. Java操作Excel概述 1.1 Excel需求概述 1.2 Excel操作三种方式对比 2. ApachePOIExc ...

  9. Linux之Ubuntu20.04安装Java JDK8的两种方式

    Linux之Ubuntu20.04远程安装Java JDK8的两种方式 安装openjdk8 更新软件包列表: sudo apt-get update 安装openjdk-8-jdk: sudo ap ...

最新文章

  1. java 重用性_提高Java代码重用性的三个方法
  2. 高效能人士的七个习惯_《高效能人士的七个习惯》导图和读后感
  3. springboot日志配置
  4. 【ArcGIS风暴】Win10操作系统ArcGIS许可License无法启动的解决方法汇总(绝对成功!)
  5. echarts map 点击地图区域变色_绘制炫酷的地图,不只是pyecharts.map!
  6. java parallel.for作用_“Parallel.For”for Java?
  7. mysql中游标能不能更新数据库_MySQL与MariaDB中游标的使用
  8. R语言自然语言处理:情感分析
  9. 初级Java代码——自制坦克大战游戏
  10. php swfobject,SWFObject基本用法实例分析_javascript技巧
  11. [南阳OJ-No.33]蛇形填数|在n*n方陈里填入1,2,...,n*n,要求填成蛇形。
  12. 基于JavaWeb的新闻发布管理系统设计与实现 毕业论文+任务书+开题报告+答辩PPT+项目源码及数据库文件
  13. ffmpeg中h264_mp4toannexb使用说明及注意事项
  14. 程序员必备的十个工具
  15. MySQL 五.索引与算法
  16. 地图--WGS84 高德坐标 百度坐标的相互转换(好用推荐)
  17. FIR窗函数和IIR模拟、数字滤波器的MATLAB实现
  18. 数学与应用数学专业考计算机研究生,数学与应用数学专业学生考研有哪些方向 数学与应用数学专业学生考研方向是怎样的...
  19. 高性能处理器架构与编程实验(基础实验2:openEuler系统环境实验)
  20. node安装node-pre-gyp报错的解决方案

热门文章

  1. Dell戴尔笔记本电脑灵越Inspiron 7591原装出厂Windows10系统恢复原厂oem系统
  2. LNK2001:无法解析外部符号_sprintf
  3. rs485接口上下拉_RS-485上拉电阻下拉电阻
  4. UNPIVOT用法详解
  5. 残差平方和(RSS)、均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)、标准差(SD)
  6. jieba库与中文分词
  7. Unity进阶:PlayMaker
  8. GitKraken Pro安装
  9. solidity:智能合约结构介绍
  10. 《HTML+CSS+JavaScript》之第4章 文本