一、知识预备

  根据使用Serializable的使用场景,可以发现所涉及的场景都是跨进程的,就是要做的事情不是在一个java进程中完成的,我们都知道java进程是基于jvm跑起来的,而每一个被创建出来的对象都是放在堆里面的,如对象实例中的属性值,但是跨进程时每个Java进程都有一个jvm,也就是各自jvm中都有一个堆用来存放对象信息(很多博客上讲的是对象存放于内存之中,简直云里雾里,新人根本搞不清楚,一定要讲到java的根本jvm)。这时候问题引入,我们如何将A进程的Student实例,传输给本机B进程呢?又或者说如何传输给另外一台机器上的C进程呢?

二、引入序列化

  我们为什么需要序列化呢?或者说什么情况下需要用到序列化呢?或者说如果没有序列化的话,哪些场景是我们处理不了的呢?
第一种情况是:一般情况下Java对象的声明周期都比Java虚拟机的要短,实际应用中我们希望在JVM停止运行之后能够持久化指定的对象,这时候就需要把对象进行序列化之后保存。
也就是说,在Java进程启动后,new出来放到内存中的对象(JVM中的堆空间),当JVM停止之后内存空间就被释放掉了,刚才创造的java进程中的世界都消失了,再次启动又会重新创建出来一个新的空间。
那么如果说是一个单机游戏进程,比如说单机版梦幻西游,人物初始属性中的攻击、防御、魔法都是0,你练了几级之后,这几个属性就会增加,那么今天你玩够了,把游戏进程给关了,那么你刚刚创建的游戏人物的相关信息都要保存下来的(很多游戏里面,在你退出的时候会提示你让你存档,就是这个意思),下次再打开游戏的时候就是将你刚才存档的信息读入到内存,在游戏界面再次的显示出来。

三、过程解析

  Java序列化是指把Java对象保存为二进制字节码的过程,Java反序列化是指把二进制码重新转换成Java对象的过程。
当然这句话也让人云里雾里,因为对象就是类的实例对象生成之后就是在内存中,这句话应该这样表达,Java序列化是指把位于堆空间的Java对象以二进制字节码的形式保存为文件,反序列化就是将文件中的二进制字节码读取解析到内存中重新转化为Java对象的过程。
 
举个例子
package test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; public class SerializableTest { public static void main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream fos = new FileOutputStream("game-person.info");
ObjectOutputStream oos = new ObjectOutputStream(fos);
GamePerson personIn = new GamePerson();
personIn.setName("abcde");
personIn.setLevel(1);
personIn.setForceValue(2);
personIn.setDefenseValue(3);
oos.writeObject(personIn);
oos.flush();
oos.close(); FileInputStream fis = new FileInputStream("game-person.info");
ObjectInputStream ois = new ObjectInputStream(fis);
GamePerson personOut = (GamePerson) ois.readObject();
System.out.println(personOut.getName());
System.out.println(personOut.getLevel());
System.out.println(personOut.getForceValue());
System.out.println(personOut.getDefenseValue());
}
} class GamePerson implements Serializable { private static final long serialVersionUID = 1L; private String name;
private int level;
private int forceValue;
private int defenseValue; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getLevel() {
return level;
} public void setLevel(int level) {
this.level = level;
} public int getForceValue() {
return forceValue;
} public void setForceValue(int forceValue) {
this.forceValue = forceValue;
} public int getDefenseValue() {
return defenseValue;
} public void setDefenseValue(int defenseValue) {
this.defenseValue = defenseValue;
} }

  

运行之后,在workspce目录下会生成game-person.info二进制文件,我们打开看看

四、修改序列化后的文件

  重点来了,现在人物属性由内存持久化到了本地,那么我们是不是可以做一些手脚?
嘿嘿,我们把十六进制中各个属性尝试改一下,999(十进制) = 3E7(十六进制),我们改序列化后的文件见下图。
然后在从文件读取看看看
public class SerializableTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("game-person.info");
ObjectInputStream ois = new ObjectInputStream(fis);
GamePerson personOut = (GamePerson) ois.readObject();
System.out.println(personOut.getName());
System.out.println(personOut.getLevel());
System.out.println(personOut.getForceValue());
System.out.println(personOut.getDefenseValue());
}
}

  

  一刀999,惊不惊喜,意不意外!

五、总结

  除了本地--内存,这种序列化的应用场景外。另外一种也就是第二种情况是:需要把Java对象通过网络进行传输的时候。因为数据只能够以二进制的形式在网络中进行传输,因此当把对象通过网络发送出去之前需要先序列化成二进制数据,在接收端读到二进制数据之后反序列化成Java对象。

关于Serializable的一个形象的例子的更多相关文章

  1. 用一个简单的例子来理解python高阶函数

    ============================ 用一个简单的例子来理解python高阶函数 ============================ 最近在用mailx发送邮件, 写法大致如 ...

  2. Spring-Context之一:一个简单的例子

    很久之前就想系统的学习和掌握Spring框架,但是拖了很久都没有行动.现在趁着在外出差杂事不多,就花时间来由浅入深的研究下Spring框架.Spring框架这几年来已经发展成为一个巨无霸产品.从最初的 ...

  3. 高仿“点触验证码”做的一个静态Html例子

    先上源码: <html> <head> <title>TouClick - Designed By MrChu</title> <meta htt ...

  4. 关于apriori算法的一个简单的例子

    apriori算法是关联规则挖掘中很基础也很经典的一个算法,我认为很多教程出现大堆的公式不是很适合一个初学者理解.因此,本文列举一个简单的例子来演示下apriori算法的整个步骤. 下面这个表格是代表 ...

  5. 一个UWSGI的例子

    摘要:uwsgi执行顺序:启动master进程,执行python脚本的公共代码(import同一层).然后生成worker进程,uwsgi.post_fork_hook=init_functions, ...

  6. 扩展Python模块系列(二)----一个简单的例子

    本节使用一个简单的例子引出Python C/C++ API的详细使用方法.针对的是CPython的解释器. 目标:创建一个Python内建模块test,提供一个功能函数distance, 计算空间中两 ...

  7. fitnesse - 一个简单的例子(slim)

    fitnesse - 一个简单的例子(slim) 2017-09-30 目录1 编写测试代码(Fixture code)2 编写wiki page并运行  2.1 新建wikiPage  2.2 运行 ...

  8. Struts2的配置和一个简单的例子

    Struts2的配置和一个简单的例子 笔记仓库:https://github.com/nnngu/LearningNotes 简介 这篇文章主要讲如何在 IntelliJ IDEA 中使用 Strut ...

  9. 一个简单的例子搞懂ES6之Promise

    ES5中实现异步的常见方式不外乎以下几种: 1. 回调函数 2. 事件驱动 2. 自定义事件(根本上原理同事件驱动相同) 而ES6中的Promise的出现就使得异步变得非常简单.promise中的异步 ...

随机推荐

  1. git的常见问题

    今天把电脑清理了下再push就出问题了 ,报这个错Failed with error: fatal: unable to access 'https://git.oschina.net/dubo_/G ...

  2. JS控制元素可见(显示)与不可见(隐藏)

    方法一: document.getElementById("id").style.visibility="hidden"; document.getElemen ...

  3. 《转》python学习(6)序列类型-字符串

    转自 http://www.cnblogs.com/BeginMan/archive/2013/06/08/3125502.html 二.序列类型 包含字符串.列表.元祖.模式都一样,举一反三即可.如 ...

  4. AndroidWear开发之下载SDK[Android W/Android L]

    Android L Developer Preview SDK发布了,但是天朝还是无法更新到.打开SDK Manager依旧一成不变,这时候就需要利器了. 第一步: 打开Goagent,不要说不知道什 ...

  5. 【Thinkphp5 】部署nginx时nginx.conf配置文件修改

    背景:thinkphp5项目 服务器环境: lnmp 1 打开路径  /usr/local/nginx/conf/vhost/ 此路径下会有你添加的域名文件夹..找到对应的域名打开. 2  代码如下, ...

  6. CRUX下实现进程隐藏(2)

    前面我们介绍了如何修改/proc目录读取函数的方法实现进程隐藏.这篇博文将介绍另一种方法—— 劫持系统调用实现进程隐藏. 其基本原理是:加载一个内核模块(LKM),通过劫持系统调用sys_getden ...

  7. Thrift Expected protocol id ffffff82 but got 0

    如果服务端配的也是noblock=false;客户端不能改成noblock=true;

  8. MySQL命令行基本命令操作

    进入命令模式后, 显示所有数据库 show databases; 选定某个数据库 use 数据库名; 创建数据库 create database 数据库名; 删除数据库 drop table 数据库名 ...

  9. 微信小程序 --- 下拉刷新上拉加载

    查看文档看到:page()函数注册页面的时候,有 onPullDownRefresh 监听用户下拉动作,onReachBottom 页面上拉触底事件的函数. 在小程序里,用户顶部下拉是默认禁止的,我们 ...

  10. DetaSet更新数据

    用到的控件:DataGridView(展示数据),                    Button控件,更名[更新] using System; using System.Collections. ...