java 序列化Serializable 详解
Java 序列化Serializable详解(附详细例子)
1、什么是序列化和反序列化
Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程。
2、什么情况下需要序列化
a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;
3、如何实现序列化
将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明这个类可以序列化。
4、序列化和反序列化例子
如果我们想要序列化一个对象,首先要创建某些OutputStream(如FileOutputStream、ByteArrayOutputStream等),然后将这些OutputStream封装在一个ObjectOutputStream中。这时候,只需要调用writeObject()方法就可以将对象序列化,并将其发送给OutputStream(记住:对象的序列化是基于字节的,不能使用Reader和Writer等基于字符的层次结构)。而反序列的过程(即将一个序列还原成为一个对象),需要将一个InputStream(如FileInputstream、ByteArrayInputStream等)封装在ObjectInputStream内,然后调用readObject()即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
package com.sheepmu; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MyTest implements Serializable { private static final long serialVersionUID = 1L; private String name= "SheepMu" ; private int age= 24 ; public static void main(String[] args) { //以下代码实现序列化 try { ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream( "my.out" )); //输出流保存的文件名为 my.out ;ObjectOutputStream能把Object输出成Byte流 MyTest myTest= new MyTest(); oos.writeObject(myTest); oos.flush(); //缓冲流 oos.close(); //关闭流 } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } fan(); //调用下面的 反序列化 代码 } public static void fan() //反序列的过程 { ObjectInputStream oin = null ; //局部变量必须要初始化 try { oin = new ObjectInputStream( new FileInputStream( "my.out" )); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } MyTest mts = null ; try { mts = (MyTest ) oin.readObject(); //由Object对象向下转型为MyTest对象 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println( "name=" +mts.name); System.out.println( "age=" +mts.age); } } |
会在此项目的工作空间生成一个 my.out文件。序列化后的内容稍后补齐,先看反序列化后输出如下:
name=SheepMu
age=24
5、序列化ID
序列化 ID 在 Eclipse 下提供了两种生成策略,一个是固定的 1L,一个是随机生成一个不重复的 long 类型数据(实际上是使用 JDK 工具生成),在这里有一个建议,如果没有特殊需求,就是用默认的 1L 就可以,这样可以确保代码一致时反序列化成功。这也可能是造成序列化和反序列化失败的原因,因为不同的序列化id之间不能进行序列化和反序列化。
6.序列化前和序列化后的对象的关系
是 "=="还是equal? or 是浅复制还是深复制?
答案:深复制,反序列化还原后的对象地址与原来的的地址不同
序列化前后对象的地址不同了,但是内容是一样的,而且对象中包含的引用也相同。换句话说,通过序列化操作,我们可以实现对任何可Serializable对象的”深度复制(deep copy)"——这意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。对于同一流的对象,他们的地址是相同,说明他们是同一个对象,但是与其他流的对象地址却不相同。也就说,只要将对象序列化到单一流中,就可以恢复出与我们写出时一样的对象网,而且只要在同一流中,对象都是同一个。
7.静态变量能否序列化
若把上面的代码中的 age变量前加上 static ,输出任然是
name=SheepMu
age=24
但是看下面的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
package com.sheepmu; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MyTest implements Serializable { private static final long serialVersionUID = 1L; private String name= "SheepMu" ; private static int age= 24 ; public static void main(String[] args) { //以下代码实现序列化 try { ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream( "my.out" )); //输出流保存的文件名为 my.out ;ObjectOutputStream能把Object输出成Byte流 MyTest myTest= new MyTest(); oos.writeObject(myTest); oos.flush(); //缓冲流 oos.close(); //关闭流 } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } fan(); //调用下面的 反序列化 代码 } public static void fan() { new MyTest().name= "SheepMu_1" ; //!!!!!!!!!!!!!!!!重点看这两行 更改部分 age= 1 ;<span style= "font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; " > //!!!!!!!!!!!!!!!!!!!重点看这两行 更改部分</span> ObjectInputStream oin = null ; //局部变量必须要初始化 try { oin = new ObjectInputStream( new FileInputStream( "my.out" )); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } MyTest mts = null ; try { mts = (MyTest ) oin.readObject(); //由Object对象向下转型为MyTest对象 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println( "name=" +mts.name); System.out.println( "age=" +mts.age); } } |
输出结果为:
name=SheepMu
age=1
为何把最上面代码的age变量添上static 后还是反序列化出了24呢?而新的从新对变量赋值的代码,不是static的得到了序列化本身的值,而static的则得到的是从新附的值。原因: 序列化会忽略静态变量,即序列化不保存静态变量的状态。静态成员属于类级别的,所以不能序列化。即 序列化的是对象的状态不是类的状态。这里的不能序列化的意思,是序列化信息中不包含这个静态成员域。最上面添加了static后之所以还是输出24是因为该值是JVM加载该类时分配的值。注:transient后的变量也不能序列化,但是情况稍复杂,稍后开篇说。
8、总结:
a)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
b)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
c) static,transient后的变量不能被序列化;
java 序列化Serializable 详解的更多相关文章
- Java 序列化Serializable详解
Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...
- Java 序列化Serializable详解(附详细例子)
Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization ...
- Java 序列化Serializable详解(附详细例子)
Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是 ...
- Java序列化格式详解
RPC的世界,由于涉及到进程间网络远程通信,不可避免的需要将信息序列化后在网络间传送,序列化有两大流派: 文本和二进制. 文本序列化 序列化的实现有很多方式,在异构系统中最常用的就是定义成人类可读的文 ...
- Serializable详解(1):代码验证Java序列化与反序列化
说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...
- Java String类详解
Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...
- Java反序列化漏洞详解
Java反序列化漏洞从爆出到现在快2个月了,已有白帽子实现了jenkins,weblogic,jboss等的代码执行利用工具.本文对于Java反序列化的漏洞简述后,并对于Java反序列化的Poc进 ...
- Java的泛型详解(一)
Java的泛型详解 泛型的好处 编写的代码可以被不同类型的对象所重用. 因为上面的一个优点,泛型也可以减少代码的编写. 泛型的使用 简单泛型类 public class Pair<T> { ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
随机推荐
- 微信公众平台:微信JS-SDK Demo
ylbtech-微信公众平台:微信JS-SDK Demo 1. HTML返回顶部 1.demo.html <!DOCTYPE html> <html> <head> ...
- C# HTML解析工具HtmlAgilityPack使用实例(一)
一.生成HTML字符串 //生成DOM字符串结构 HtmlNode container = HtmlNode.CreateNode("<div />"); HtmlNo ...
- CF-832B
B. Petya and Exam time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- 洛谷 - P4861 - 按钮 - 扩展大步小步算法
https://www.luogu.org/problemnew/show/P4861 把好像把一开始b==1的特判去掉就可以AC了. #include<bits/stdc++.h> us ...
- 算法学习--Day8
今天重拾算法复习. 今天学习了两个类型的算法——并查集与最小生成树(MST) 简单记录一下并查集的大致内容. 一.并查集的内容大致作用为查找当前图中的点有几个集合. 该算法起到查询分组的情况.通过给定 ...
- uoj#418. 【集训队作业2018】三角形(线段树合并)
传送门 好迷啊--膜一下ljz 考虑每个操作,如果把操作按先后顺序放到序列上的话,操作一就是把\(w_i\)的石子放到某个节点,那么就是在序列末端加入\(w_i\),然后根据贪心肯定要把它所有儿子的石 ...
- git上如何删除已有项目
删除fork别人的项目 由于最近想删除fork别人项目,步骤如下. 点击进入需要删除fork的项目 进入Settings选项 找到delete this repository按钮 确认是否要删除,Pl ...
- ACM2015沈阳:B-Bazinga
2019.1.24 数据范围:\(n<=500,m<=2000\) 这个题最裸的暴力就是对于每个字符串,都去验证一次,时间复杂度\(O(n^2m)\) 我们发现,如果对于字符串\(i\), ...
- PyInstaller 库
将.py 源代码转换成无需源代码的可执行文件 首先,PyInstaller是第三方库,需要下载额外安装(安装第三方库需要使用pip工具) 步骤: 1.用管理员运行cmd命令行 "pip in ...
- 自定义的cell上面有图片时,如果产生了重用,图片可能会错乱问题
当被重用的cell将要显示时,会调用这个方法,这个方法最大的用武之地是当你自定义的cell上面有图片时,如果产生了重用,图片可能会错乱(当图片来自异步下载时及其明显),这时我们可以重写这个方法把内容抹 ...