什么是序列化?

Java序列化是在JDK 1.1中引入的,是Java内核的重要特性之一。

Java序列化API允许我们将一个对象转换为流,并通过网络发送,或将其存入文件或数据库以便未来使用,

反序列化则是将对象流转换为实际程序中使用的Java对象的过程。

序列化有啥用?

1.暂存大对象

2.Java对象需要持久化的时候

3.需要在网络,例如socket中传输Java对象

    因为数据只能够以二进制的形式在网络中进行传输,因此当把对象通过网络发送出去之前需要先序列化成二进制数据,在接收  端读到二进制数据之后反序列化成Java对象

4.深度克隆(复制)

5.跨虚拟机通信

代码怎么写?

1.序列化例子

实体类:Student.java

package com.dylan.serialization;

import java.io.Serializable;

/**
* 学生类
*
* @author xusucheng
* @create 2018-01-08
**/
public class Student implements Serializable { private int id;
private String name;
private String gender; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getGender() {
return gender;
} public void setGender(String gender) {
this.gender = gender;
} public Student(int id, String name, String gender) {
this.id = id;
this.name = name;
this.gender = gender;
} @Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
'}';
}
}
package com.dylan.serialization;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List; /**
* 序列化例子
*
* @author xusucheng
* @create 2018-01-08
**/
public class SerializationDemo {
public static void main(String[] args) throws IOException{
//学生1
Student s1 = new Student(101,"Jack","Male");
//学生2
Student s2 = new Student(102,"Lily","Female"); List<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2); //创建文件流
FileOutputStream fos = new FileOutputStream("D:\\test\\student01.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(list); os.close();
System.out.println("序列化完成!");
}
}

2.反序列化例子

package com.dylan.serialization;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List; /**
* 反序列化例子
*
* @author xusucheng
* @create 2018-01-08
**/
public class DeserializationDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\test\\student01.ser");
ObjectInputStream is = new ObjectInputStream(fis);
Object obj = null;
List<Student> list = new ArrayList<>();
try {
list = (List<Student>)is.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} is.close(); //遍历list,输出
for (Student student:list){
System.out.println(student.toString());
}
}
}

3.serialVersionUID的作用

可以看到上面序列化例子中的学生实体类只是实现了Serializable接口,假如我现在接到客户需求,要调整Student类,增加学生年龄属性,调整后如下:

public class Student implements Serializable {

    private int id;
private String name;
private String gender;
private int age;
...

此时,我在去执行反序列化程序,结果报错了:

啥玩意?就是说Stuent类调整后,其序列化版本ID发生了变化,java又是根据这个ID来判断是不是同一个类。ID不一样则无法反序列化!

事实上如果一个类没有定义serialVersionUID,它会自动计算出来并分配给该类。当发生以下情况,这个ID就会改变:

  • 在类中添加一些新的变量。
    将变量从transient转变为非tansient,对于序列化来说,就像是新加入了一个变量而已
    将变量从静态的转变为非静态的,对于序列化来说,就也像是新加入了一个变量而已

这个时候就需要我们手动指定这个serialVersionUID了,它告诉jvm,嗨,这个学生类我更新了一下,反序列化的时候记得尽量向后兼容,别报错。通常我们有以下几种方式:

serialVersionUID生成方式:

1)直接写固定的1L;

2)利用JDK自带serialver命令:切到类路径下

3)IDEA生成serialVersionUID

Intellij IDEA 默认没启用这个功能



Preferences->Editor->Inspections->Serialization issues->Serializable class without serialVersionUID 勾上

应用之后就开启了检测功能

在你的class名前(一定是光标移动到类名前):按(mac:option+return)或者( win:Alt+Enter) 就会提示自动创建 serialVersionUID 了。

加上serialVersionUID后的实体类如下:

public class Student implements Serializable {

    private static final long serialVersionUID = -2110227637642817458L;

    private int id;
private String name;
private String gender;
private int age;
...

再次执行反序列化又恢复正常了:

Student{id=101, name='Jack', gender='Male'}
Student{id=102, name='Lily', gender='Female'}

在这里有一个建议,如果没有特殊需求,就是用默认的 1L 就可以,这样可以确保代码一致时反序列化成功。

那么随机生成的序列化 ID 有什么作用呢,有些时候,通过改变序列化 ID 可以用来限制某些用户的使用。

4.static和transient属性无法序列化

transient翻译过来就是短暂的,瞬时的。如果在可序列化的类中某个成员变量加了这个修饰,则说明它只在jvm运行时才保存值,序列化时不会保存的。

为了证明这一点,我们调整一下Student类,加入1个静态变量mess和1个transient变量password。调整后的类如下:

package com.dylan.serialization;

import java.io.Serializable;

/**
* 学生类
*
* @author xusucheng
* @create 2018-01-08
**/
public class Student implements Serializable { private static final long serialVersionUID = -2110227637642817458L;
private static String mess="null"; private int id;
private String name;
private String gender;
private int age;
private transient String password; public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getGender() {
return gender;
} public void setGender(String gender) {
this.gender = gender;
} public Student(int id, String name, String gender) {
this.id = id;
this.name = name;
this.gender = gender;
mess = "something";
} @Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", password='" + password + '\'' +
", mess='" + mess + '\'' +
'}';
}
}

再次执行序列化,反序列化后:

结论没问题。

5.序列化实战:Socket传输序列化对象例子

package com.dylan.serialization;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket; /**
* @author xusucheng
* @create 2018-01-08
**/
public class Server {
public static void main(String[] args) { //The client is used to handle connections with a client once a connection is
//established.
Socket client = null; //The following two objects handles our Serialization operations, ObjectOutputStream
//writes an object to the stream. ObjectInputStream reads an object from the stream.
ObjectOutputStream out = null;
ObjectInputStream in = null; try {
ServerSocket server = new ServerSocket(8888);
client = server.accept();
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream()); Student student = (Student) in.readObject();
System.out.println(student); // close resources
out.close();
in.close();
client.close();
server.close(); } catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
package com.dylan.serialization;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException; /**
* @author xusucheng
* @create 2018-01-08
**/
public class Client {
public static void main(String[] args) {
Socket client = null;
ObjectOutputStream out = null;
ObjectInputStream in = null; try { client = new Socket("127.0.0.1", 8888);
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream()); Student student = new Student(991,"Dylan","Male");
out.writeObject(student);
out.flush(); out.close();
in.close();
client.close(); } catch (UnknownHostException e) {
e.printStackTrace();
System.exit(1);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
} }
}

说明:假如Student类没有实现序列化接口,在执行Client程序时会报错:

正如我们前面所讲,网络只能传输二进制数据,Java对象要想传输必须先序列化。

运行效果:

以上只是讲解了一下序列化的常用知识点,还有些深入的部分,以后有空再总结。

Java序列化(Serializable)与反序列化详解的更多相关文章

  1. Java 序列化Serializable详解

    Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...

  2. Java 序列化Serializable详解(附详细例子)

    Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization ...

  3. java 序列化Serializable 详解

    Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是 ...

  4. Java 序列化Serializable详解(附详细例子)

    Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是 ...

  5. java 深拷贝与浅拷贝机制详解

    概要: 在Java中,拷贝分为深拷贝和浅拷贝两种.java在公共超类Object中实现了一种叫做clone的方法,这种方法clone出来的新对象为浅拷贝,而通过自己定义的clone方法为深拷贝. (一 ...

  6. Java I/O : Java中的进制详解

    作者:李强强 上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算.这一讲,泥瓦匠带你走进Java中的进制详解. 一.引子 在Java世界里,99%的工作都是处理这高层. ...

  7. Java 序列化Serializable具体解释(附具体样例)

    Java 序列化Serializable具体解释(附具体样例) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描写叙述的过程:反序列化deserializa ...

  8. java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET

    java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了!      社区福利快来领取免费参加MDCC大会机会哦    Tag功能介绍—我们 ...

  9. Java开发利器Myeclipse全面详解

    Java开发利器Myeclipse全面详解: Ctrl+1:修改代码错误 Alt+Shift+S:Source命令 Ctrl+7:单行注释 Ctrl+Shift+/ :多行注释 Ctrl+I :缩进( ...

  10. Java中的main()方法详解

    在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的方法有很大的不同,比如方法的名字必须是main,方法必须是 ...

随机推荐

  1. [转帖]TPC-C 、TPC-H和TPC-DS区别

    https://zhuanlan.zhihu.com/p/339886289 针对数据库不同的使用场景TPC组织发布了多项测试标准. TPC-C: TPC Benchmark C于1992年7月获得批 ...

  2. [转帖]KVM调整磁盘大小

    https://www.jianshu.com/p/5ca598424eb9 一台win10的虚拟机磁盘空间不足了,需要调整磁盘的大小.上网搜索KVM调整磁盘大小,结果得出的博客都说只有raw格式的能 ...

  3. 使用Grafana + jmx 监控 kafka3.5 的过程

    使用Grafana + jmx 监控 kafka3.5 的过程 摘要 周五一边进行数据库监控, 同时想着部署一套监控系统. 能够监控一下kafka等中间件 结果不想自己遇到了很多坑. 下午有同事语音告 ...

  4. [转帖]fio工具中的iodepth参数与numjobs参数-对测试结果的影响

    测试环境 3台服务器:ceph配置内外网分离,外网使用万兆线,内网使用千兆线,osd共21个. 1台客户端:安装fio工具.内核客户端,使用万兆线. 测试目的 针对fio工具中的iodepth(队列深 ...

  5. [转帖]金仓数据库KingbaseES V8R6 中unlogged表

    KingbaseESV8R6有一种表称为unlogged,在该表新建的索引也属于unlogged.和普通表的区别是,对该表进行DML操作时候不将该表的变更记录变更写入到wal文件中.在数据库异常关机或 ...

  6. [转帖]Linux开发环境——SCL软件集

    一.SCL简介 1.SCL简介 SCL(Software Collections)是一个CentOS/RHEL Linux平台的软件多版本共存解决方案,为RHEL/CentOS  Linux用户提供一 ...

  7. SPEC2006的学习与总结

    SPEC2006的学习与总结 摘要 最近特别想进行一些性能验证工作. 所以研究了spec2006 然后想整理一下之前的内容. 想着将内容整理一下. 这次主要是抄别人的. 知识来源: https://b ...

  8. awk中的NR,FNR ,NF,$NF,RS,ORS,FS,OFS

    awk中的NR,FNR ,NF,$NF,RS,ORS,FS,OFS https://www.cnblogs.com/zhangqingsh/archive/2013/04/24/3040801.htm ...

  9. React类组件中事件绑定this指向的三种方式

    有状态组件和无状态组件 函数组件又叫做无状态组件,类组件又叫做有状态组件. 状态又叫做数据 函数组件没有自己的状态,只负责静态页面的展示. 我们可以理解为纯ui展示.() 类组件有自己的状态,扶着更新 ...

  10. Object.defineProperty熬夜整理的用法,保证你看的明白!

    Object.defineProperty的基本使用 <script> let personObj={ name:'何西亚', sex:'男' } //我们想给这个对象添加一个属性 // ...