java----序列化与反序列化中及java序列化本质就是存储一个对象,然后在其他地方在调用它
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=aaaa //对象变量只能被对象自己更改,所以可以通过序列化存储起来
age=1 //类变量可以被所有实例对象更改
这是因为,对象实例myTest在序列化时被保存到my.out文件中,在反序列化时又被取出运算,但序列化的对象只保存非static与transient的成员变量的状态,所以myTest.name="aaaa"被保存起来,而age是类变量,不被序列化,与类信息同在方法区,能够被所有对象更改。
但是看下面的例子:
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(); myTest.name="aaaaa";
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=aaaaa
age=1
为何把最上面代码的age变量添上static 后还是反序列化出了24呢?而新的从新对变量赋值的代码,不是static的得到了序列化本身的值,而static的则得到的是从新附的值。原因: 序列化会忽略静态变量,即序列化不保存静态变量的状态,而调用静态变量输出其值时会根据对象声明的数据结构去找该变量,如果没找到在到方法区中找静态变量,因为静态变量与类信息存放在方法区中,所有进程共享方法区,即可以更改静态变量。静态成员属于类级别的,所以不能序列化。即 序列化的是对象的状态不是类的状态。这里的不能序列化的意思,是序列化信息中不包含这个静态成员域。最上面添加了static后之所以还是输出24是因为该值是JVM加载该类时分配的值。注:transient后的变量也不能序列化,但是情况稍复杂,稍后开篇说。
8、总结:
a)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
b)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
c) static,transient后的变量不能被序列化;
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
java----序列化与反序列化中及java序列化本质就是存储一个对象,然后在其他地方在调用它的更多相关文章
- 利用php的序列化和反序列化来做简单的数据本地存储
利用php的序列化和反序列化来做简单的数据本地存储 如下程序可以做为一个工具类 /** * 利用php的序列化和反序列化来做简单的数据本地存储 */ class objectdb { private ...
- java序列化和反序列化中的serialVersionUID有啥用
1.什么是序列化和反序列化 序列化就是将java对象转成字节序列的过程:反序列化就是将字节序列转成java对象的过程. java中,序列化的目的一种是需要将对象保存到硬盘上,一种是对象需要在网络中传 ...
- JAVA中序列化和反序列化中的静态成员问题
关于这个标题的内容是面试笔试中比较常见的考题,大家跟随我的博客一起来学习下这个过程. ? ? JAVA中的序列化和反序列化主要用于: (1)将对象或者异常等写入文件,通过文件交互传输信息: (2)将对 ...
- 序列化与反序列化中serialVersionUID的作用(通俗易懂)
serialVersionUID:字面意思上是序列化的版本号,这个在刚刚接触java编程时,学序列化大家一般都不会注意到,在你一个类序列化后除非你强制去掉了myeclipse中warning的功能,在 ...
- PHP序列化以及反序列化系列[1]--PHP序列化格式的写法
反序列化:对单一的已序列化的变量进行操作,将其转换回 PHP 的值(zval). PHP序列化方式 PHP在序列化的时候会将相应的变量以对应的键值进行储存. 将一个类序列化的话,处理代码主要的 文件: ...
- json数组的序列化和反序列化json数组的序列化和反序列化
如题,我就不多说了,自己看代码的,很好理解 using System; using System.Collections.Generic; using System.Web; using System ...
- Java学习笔记-----eclipse中建立Java项目并成功运行
环境:WIN7 64位 +eclipse 2018 12version 具体方法:https://jingyan.baidu.com/album/9c69d48fefa53113c9024eb3.ht ...
- K:java中的序列化与反序列化
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?以下内容将围绕这些问题进行展开讨论. Java序列化与反序列化 简单来说Java序列化是指把Java对象转 ...
- Java中的序列化与反序列化
序列化定义 将对象转换为字节流保存起来,并在以后还原这个对象,这种机制叫做对象序列化. 将一个对象保存到永久存储设备上称为持久化. 一个对象要想能够实现序列化,必须实现java.io.Serializ ...
随机推荐
- 苹果开发——向App Store提交应用
原地址:http://zengwu3915.blog.163.com/blog/static/2783489720137410539278/ 完成一个app应用后,肯定是要提交的,下面聊一下关于向Ap ...
- PotPlayer 如何设置多屏幕全屏播放
如何在播放器中,设置扩展播放模式? 全屏设置/主全屏显示设备:Display2 如何使视频播放时,没有黑边并且全屏充满? 高宽比/处理方式:保持全屏宽高比 如果取消掉视频上方的文字提示信息 ...
- 36、TreeSet详解
TreeSet是SortedSet接口的实现类,TreeSet可以保证元素处于排序状态.与HashSet相比,TreeSet还提供了如下几个而外的方法: 1).Comparator comparato ...
- vcs github gitlab git名词解释
vcs:version control system git:一个版本管理工具,从git上clone,除了代码,还会把版本信息也给你clone下来. github:一个基于git的代码管理网站,支持公 ...
- Linux命令-文件处理命令:ln
ln -s /etc/issue /tmp/issue.soft 为这个/etc/issue文件创建一个软连接,名称为/tmp/issue.soft(相当于windows里面给/etc/issue文件 ...
- 帧率(FPS)计算的六种方法总结
原文地址:http://blog.csdn.net/u012494876/article/details/53368164 帧率(FPS)计算是游戏编程中常见的一个话题.大体来说,总共有如下六种方法: ...
- 火狐浏览器(firefox)中js要注意的问题
1.出现错误调用error方法或者ajax请求了多次,那么极有可能是异步请求的原因. 添加 async : false , -> async. 默认是 true,即为异步方式,$.aja ...
- C#:设置控件样式(待补充)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...
- 跨域JSONP原理及调用详细演示样例
上篇博客介绍了同源策略和跨域訪问概念,当中提到跨域经常使用的基本方式:JSONP和CORS. 那这篇博客就介绍JSONP方式. JSONP原理 在同源策略下,在某个server下的页面 ...
- 【实用代码片段】将json数据绑定到html元素 (转)
jQuery扩展 jQuery.fn.extend({ 'jsonBind':function(json){ var dom=this; dom.find('[json-bind]').each(fu ...