Java基础之序列化
最近几天重新看了下序列化部分的内容,今天将它整理出来。
- 什么是序列化/反序列化
序列化是java开发中经常可以听到的一个词,那么究竟什么是序列化呢?简单来理解的话就是:将java对象转换成字节序列以二进制数据的形式保存在本地的操作就叫做序列化,将二进制数据还原成java对象的过程就叫反序列化。
我们画一个图来说明下:
2.怎么让对象序列化/反序列化
虽然序列化的目的是为了操作java对象,但并不是所有的java对象都可以进行序列化,想要实现序列化首需实现Serializable接口或者Externalizable接口,本文主要介绍Serializable接口。
我们先来看下java.io.Serializable接口:
可以看到这个接口仅仅是个标记,代表这个类可以序列化,没有任何方法,通过上面的@see注解可以知道它和对象处理流有关。
现在我们已经知道只要一个类实现了Serializable接口,就代表这个类可以序列化,那么通过什么操作可以将这个java对象以二进制数据的形式保存到本地呢?就是上面@see提到的对象处理流ObjectStream,我们写一个实例来了解一下整个过程:
可序列化的java对象:
package com.ljw.serialzable;import java.io.Serializable;/*** @author liu.jiawei* @create 2018-08-29 22:52**/
public class Dog implements Serializable{public String type;public String name;public int age;public Dog(String type, String name, int age) {this.type = type;this.name = name;this.age = age;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
序列化过程:
package com.ljw.serialzable;import java.io.*;/*** @author liu.jiawei* @create 2018-08-29 22:29**/
public class TestSerializeDog {public static void main(String[] args) {File file = new File("Dog.txt");try (FileOutputStream fis = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fis)) {Dog dog = new Dog("藏獒", "旺财", 1);oos.writeObject(dog);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}
运行结果:
可以看到通过ObjectOutputStream这个对象处理流,可以实现java对象的序列化,处理流需要基于节点流发挥作用,ObjectOutputStream需要配合FileOutputStream一起使用。
看了序列化的过程,我们再将保存dog对象的文件重新还原成java对象:
package com.ljw.serialzable;import java.io.*;/*** @author liu.jiawei* @create 2018-08-29 23:01**/
public class TestDeserializeDog {public static void main(String[] args) {File file = new File("/Users/liujiawei/ztesoft/JSYD/leetcode/dog.txt");try (FileInputStream fis = new FileInputStream(file);ObjectInputStream ois = new ObjectInputStream(fis)) {Dog dog = (Dog) ois.readObject();System.out.println(dog.getType() + "===" + dog.getName() + "===" + dog.getAge());} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
可以看到,与序列化过程基本相似,只是ObjectOutputStream换成了ObjectInputStream,writeObject换成了readObject,类型强转程了需要的java 对象,这样就将之前的二进制数据还原成了对应的java对象。
还是上面的图来说明下过程:
3.序列化中的注意细节
- serialVersionUID
通过上面的两个例子,我们已经大概了解序列化和反序列化的过程,还有些细节需要我们注意,还是上面的dog对象,我们增加一个成员变量:
public int height;
再重新执行一下刚刚的反序列化的代码,是不是觉得很奇怪,这个两者有什么联系么?我们运行下代码:
是不是运行出错了,看它的报错提示我们可以知道有两个id不同导致了报错,这个id是干什么的呢?
这里面涉及到一个概念叫序列id(serialVersionUID),这个jvm在序列化操作文件时用来判断的一个变量,一般来说同一个class文件在不同情况编译的出来的serialVersionUID都是不同的,这就会导致了上面的那个情况,所以我们在声明一个java类是可序列化的时候,同时会定义一个静态常量serialVersionUID,idea可以对class生成对应的serialVersionUID,或者直接加上:
public static final long serialVersionUID = 1L;
*多个class可以用同一个serialVersionUID,并不影响判断。
我们在Dog类中加上serialVersionUID,重新执行反序列化过程,可以正常执行。
- transient
一个可序列化的java对象,有些时候,我们并不想暴露所有的成员变量,只需要在对应的变量前加上transient关键字,那么这个变量就不会被被序列化了,在反序列化的时候也就只能获取对应类型的默认值了。
我们将Dog类中的年龄字段隐藏:
public transient int age;
重新执行下反序列化过程,看下运行结果有没有不同:
可以看到,我们虽然反序列化了对象,但是并没有拿到隐藏的字段的值。
4.序列化思考
(1)子类没有实现序列化接口,基类实现,子类可以序列化么?
(2)子类实现序列化接口,基类没有实现,子类可以序列化么?
(3)内部类实现序列化接口,外部类没有实现,内部类可以序列化么?
废话不多说,直接上代码来一个个测试下:
(1):
子类:
package com.ljw.serialzable;/*** @author liu.jiawei* @create 2018-08-29 23:35**/
public class Man extends Person{public String name;public Man(String sex) {super(sex);}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
基类:
package com.ljw.serialzable;import java.io.Serializable;/*** @author liu.jiawei* @create 2018-08-29 23:34**/
public class Person implements Serializable {public String sex;public Person(String sex) {this.sex = sex;}
}
序列化:
package com.ljw.serialzable;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;/*** @author liu.jiawei* @create 2018-08-29 23:36**/
public class TestSerializeMan {public static void main(String[] args) {try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("man.txt"))) {oos.writeObject(new Man("man"));} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
运行结果:
结论:可以
(2)
子类:
package com.ljw.serialzable;import java.io.Serializable;/*** @author liu.jiawei* @create 2018-08-29 23:39**/
public class Cat extends Animal implements Serializable{public String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public Cat(String type) {super(type);}public Cat(String type, String name) {super(type);this.name = name;}
}
基类:
package com.ljw.serialzable;/*** @author liu.jiawei* @create 2018-08-29 23:39**/
public class Animal {public String type;public Animal(String type) {this.type = type;}
}
序列化:
package com.ljw.serialzable;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;/*** @author liu.jiawei* @create 2018-08-29 23:40**/
public class TestSerializeCat {public static void main(String[] args) {try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cat.txt"))) {oos.writeObject(new Cat("波斯猫"));} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
运行结果:
结论:可以
(3)
包含内部类的外部类:
package com.ljw.serialzable;import com.ljw.ColleactionAndMap.T;import java.io.*;/*** @author liu.jiawei* @create 2018-08-29 23:43**/
public class TestInnerClass {class Dog implements Serializable{public String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public Dog(String name) {this.name = name;}}public static void main(String[] args) {try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ddd.txt"))) {TestInnerClass testInnerClass = new TestInnerClass();TestInnerClass.Dog dog = testInnerClass.new Dog("旺财");oos.writeObject(dog);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
运行结果:
结论:不可以,外部类也必须实现序列化接口。
Java基础之序列化相关推荐
- Java基础之序列化对象Serialized
文章目录 序列化对象Serialized 目的: 序列化类型 应用场景 代码案例 直接应用 自定义对象序列化 序列化对象Serialized 目的: 序列化机制允许将实现序列化的Java对象转换成字节 ...
- 【Java基础】序列化之serialVersionUID
为什么需要serialVersionUID? 序列化很大部分的作用是持久化到本地中,那么有个问题就是如果在还原也就是反序列化这些本地数据的时候,原先的类结构已经发生了改变,存在本地的数据代表着的是旧的 ...
- java基础----IO序列化Serializable
package com.henu.io; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io ...
- Java基础之序列化(类属性由驼峰转换成下划线)
用Google的gson可以实现 1. 引入依赖 <dependency><groupId>com.google.code.gson</groupId><ar ...
- Java基础—序列化底层原理
原文地址:https://blog.csdn.net/xlgen157387/article/details/79840134 目录 一.基本概念 二.Java如何实现序列化和反序列化 三.相关注意事 ...
- 【重难点】【Java基础 04】值传递和引用传递、序列化和反序列化
[重难点][Java基础 04]值传递和引用传递.序列化和反序列化 文章目录 [重难点][Java基础 04]值传递和引用传递.序列化和反序列化 一.值传递和引用传递 1.对比 二.序列化 1.基本概 ...
- Java基础-22总结登录注册IO版,数据操作流,内存操作流,打印流,标准输入输出流,转换流,随机访问流,合并流,序列化流,Properties...
你需要的是什么,直接评论留言. 获取更多资源加微信公众号"Java帮帮" (是公众号,不是微信好友哦) 还有"Java帮帮"今日头条号,技术文章与新闻,每日更新 ...
- 夯实Java基础系列22:一文读懂Java序列化和反序列化
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- java基础巩固-宇宙第一AiYWM:为了维持生计,手写RPC~Version07(RPC原理、序列化框架们、网络协议框架们 、RPC 能帮助我们做什么呢、RPC异常排查:ctrl+F搜超时)整起
上次Version06说到了咱们手写迷你版RPC的大体流程, 对咱们的迷你版RPC的大体流程再做几点补充: 为什么要封装网络协议,别人说封装好咱们就要封装?Java有这个特性那咱就要用?好像是这样.看 ...
- Java基础-22总结登录注册IO版,数据操作流,内存操作流,打印流,标准输入输出流,转换流,随机访问流,合并流,序列化流,Properties
你需要的是什么,直接评论留言. 获取更多资源加微信公众号"Java帮帮" (是公众号,不是微信好友哦) 还有"Java帮帮"今日头条号,技术文章与新闻,每日更新 ...
最新文章
- Python第三方库jieba(中文分词)入门与进阶(官方文档)
- 一张贴纸骗过AI识别?对抗性机器学习是什么东西?
- 没有最快,只有更快!富士通74.7秒在ImageNet上训练完ResNet-50
- Json数据发布到Tomcat本地服务器
- Python 常见优化技巧,让你的程序溜溜的跑起来!
- esp32-智能语音-录音(保存于SD卡)
- 第一个smarty例子--分页显示数据
- python:from skimage.measure import find_contours
- 虚拟机中的linux系统无法获得ip(ifconfig命令无法查到ip)
- android内存泄漏MAT,利用Android Studio、MAT对Android进行内存泄漏检测
- 网页调用智能IC卡读写器的解决方案
- 基于OpenCV与 ImageAI 的动漫人物识别
- Kinect人体扫描的多级主动配准:从低质量到高质量
- c# RestClient 请求接口
- 解决Keil4与Keil5在同系统不能共存的问题
- ips细胞治疗糖尿病研究进展综述
- Android界面开发基础
- DWR 实现AJAX学习
- ETHZ 计算机视觉实验室招聘医学图像分析方向博士后研究员
- Centos 进入recovery模式,单用户模式