JAVA中序列化和反序列化中的静态成员问题
关于这个标题的内容是面试笔试中比较常见的考题,大家跟随我的博客一起来学习下这个过程。
? ? JAVA中的序列化和反序列化主要用于:
(1)将对象或者异常等写入文件,通过文件交互传输信息;
(2)将对象或者异常等通过网络进行传输。
? ? 那么为什么需要序列化和反序列化呢?简单来说,如果你只是自己同一台机器的同一个环境下使用同一个JVM来操作,序列化和反序列化是没必要的,当需要进行数据传输的时候就显得十分必要。比如你的数据写到文件里要被其他人的电脑的程序使用,或者你电脑上的数据需要通过网络传输给其他人的程序使用,像服务器客户端的这种模型就是一种应用,这个时候,大家想想,每个人的电脑配置可能不同,运行环境可能也不同,字节序可能也不同,总之很多地方都不能保证一致,所以为了统一起见,我们传输的数据或者经过文件保存的数据需要经过序列化和编码等操作,相当于交互双方有一个公共的标准,按照这种标准来做,不管各自的环境是否有差异,各自都可以根据这种标准来翻译出自己能理解的正确的数据。
? ? 在JAVA中有专门用于此类操作的API,供开发者直接使用,对象的序列化和反序列化可以通过将对象实现Serializable接口,然后用对象的输入输出流进行读写,下面看一个完整的例子。
上面这段程序是定义了要被序列化和反序列化的类DataObject,这个类实现了Serializable接口,里面有几点需要注意:
(1)类中有一个静态成员变量i,这个变量能不能被序列化呢?等下通过测试程序看一下;
(2)类中重写了toString方法,是为了打印结果。
? ? 接下来我们看一下测试该类的对象序列化和反序列化的一个测试程序版本,提前说明,这个版本是有问题的。
? 上面这段程序大家可以直接运行。注意,这里定义了两个方法Serialize()和Deserialize(),分别实现了序列化和反序列化的功能,里面的主要用到了对象输入输出流和文件输入输出流,大家看一下程序中的注释就可以理解。在序列化的方法中,将对象的成员变量word设置成了"123",i设置成了"2",注意这里的i是静态变量,那么以通常的序列化和反序列化的理解来看,无非就是一个正过程和一个逆过程,最终经过反序列化后,输出对象中的word和i时,大家一般都觉得应该还是"123"和"2",那么上面程序的运行结果确实就是:
?这样会使得大家觉得理应就是如此,其实这是错误的。大家要记住:?
?
? ? 静态成员属于类级别的,所以不能序列化,序列化只是序列化了对象而已,这里“不能序列化”的意思是序列化信息中不包含这个静态成员域,下面之所以i输出还是2,是因为测试都在同一个机器(而且是同一个进程),因为这个jvm已经把i加载进来了,所以获取的是加载好的i,如果是传到另一台机器或者关掉程序重新写个程序读入DataObject.txt,此时因为别的机器或新的进程是重新加载i的,所以i信息就是初始时的信息,即0。所以,总结来看,静态成员是不能被序列化的,静态成员定以后的默认初始值是0,所以正确的运行结果应该是:
那么既然如此,怎样才能测试出正确的结果呢?大家注意,上面的程序是直接在一个JVM一个进程中操作完了序列化和反序列化的所有过程,故而JVM中已经保存了i=2,所以i的值没有变化,所以再次读出来肯定还是2。如果想得出正确的结果,必须在两个JVM中去测试,但是大家的电脑很难做到这种测试环境,所以可以通过以下方法来测试。
??上面这个类只用来进行序列化,对象被序列化后保存在文件"DataObject.txt"中,然后程序运行结束,JVM退出。接下来看另一段程序。
?上面这段程序用来实现对象的反序列化,它从文件"DataObject.txt"中读出对象的相关信息,然后进行了反序列化,最终输出对象中word和i的值,这个程序输出的结果才是word="123", i=0 这个才是正确的结果,这是因为序列化和反序列化都有自己的main方法,先序列化,然后JVM退出,再次运行反序列化,JVM重新加载DataObject类,此时i=0,"DataObject.txt"文件中其实是没有i的信息的,只有word的信息。这里通过先后执行序列化和反序列化,让JVM得到一次重新加载类的机会,模拟了两个JVM下运行的结果。
? ? 总之,大家要记住以下几点:
(1)序列化和反序列化的实现方法和应用场合;
(2)静态成员是不能被序列化的,因为静态成员是随着类的加载而加载的,advice可数吗与类共存亡,并且静态成员的默认初始值都是0;
(3)要明白错误的那个测试程序的原因,搞明白JVM的一些基本机制;
(4)要想直接通过打印对象而输出对象的一些属性信息,要重写toString方法。
? ?上面只是我的一些个人总结,欢迎大家指正和补充。
本文转自:https://blog.csdn.net/dan15188387481/article/details/49977421
相关阅读:
如何准备Java初级和高级的技术面试
Java transient关键字使用小记
文章来源:https://blog.csdn.net/rlnLo2pNEfx9c/article/details/81161472
JAVA中序列化和反序列化中的静态成员问题的更多相关文章
- Java 中序列化与反序列化
一. 序列化和反序列化概念 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.将程序中的对象,放入文 ...
- Java 中序列化与反序列化引发的思考?
java 中序列化指从对象转变为 二进制流的过程中需要进行序列化,而反序列化指二进制流转换为java 对象.那么有的时候java 存储到数据库不需要序列化, 而计算机系统本质存储的就是二进制文件,数据 ...
- java 对象序列化与反序列化
Java序列化与反序列化是什么? 为什么需要序列化与反序列化? 如何实现Java序列化与反序列化? 本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为 ...
- Java对象序列化和反序列化的工具方法
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...
- Java之序列化和反序列化
序列化的对象: package test_demo.SerializableOper; import java.io.Serializable; /* * 序列化对象需要实现序列号接口 * */ pu ...
- Java基础—序列化与反序列化(转载)
转载自: Java序列化与反序列化 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 2.为什么需要序列化 ...
- Java对象序列化与反序列化一 JSON
Java对象序列化与反序列化一 JSON 1. 依赖库 jackson-all-1.6.1.jar 2. 代码 public class Student { private String nam ...
- java之序列化与反序列化
1.这里主要是介绍Protobuf提供的序列化与反序列化的高效性.相对于传统的java提供的序列化来说,Protobuf的效率提高了很多倍.但是也有不足的地方,就是proto在对象序列化的时候抛弃了很 ...
- java序列化和反序列化中的serialVersionUID有啥用
1.什么是序列化和反序列化 序列化就是将java对象转成字节序列的过程:反序列化就是将字节序列转成java对象的过程. java中,序列化的目的一种是需要将对象保存到硬盘上,一种是对象需要在网络中传 ...
随机推荐
- netsh命令获取wifi历史连接密码
首先[win+r]快捷键打开运行,输入cmd.或点击左下角win-运行-cmd 1.netsh wlan show profiles //列出所有的ap名称 2.netsh wlan show pro ...
- Linux命令:date命令
date命令作用:显示和设置系统的日期和时间 一.设置系统日期时间 格式:date [MMDDhhmm[[CC]YY][.ss]] 举例:将当前系统时间改为 2020年10月1日12点10分 # da ...
- IOS switch-case知多少
1. switch参数类型 switch参数类型要求是integer type,准确来讲,是可以转换成integer的类型, 这包括所有的C基本数据类型((signed/unsigned)char, ...
- C# webkit 内核浏览器 访问https 网站 提示 Problem with the SSL CA cert (path? access rights?)
C# webkit 内核浏览器 访问https 网站 提示 Problem with the SSL CA cert (path? access rights?) 解决方法: 陈凯文11112014- ...
- Jackson自定义反序列化
// 设置jackson时间反系列化格式 SimpleModule module = new SimpleModule(); module.addDeserializer(Date.class, ne ...
- 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:对象的多态性
class A{ // 定义类A public void fun1(){ // 定义fun1()方法 System.out.println("A --> public void fun ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:插入符
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- git使用问题一新建本地仓库添加远程合并推送
1,git远程新建仓库demo 2,git本地初始化仓库demo 3,git本地添加远程仓库 git remote add <name> <url> 4,git把远程仓库pul ...
- 回过头来看一看过去20年的十大IT趋势
导读 这是一个概念,不是一个事物.其实,可以认为当组织的数据增长速度超过IT部门的管理能力时,大数据就开始了.此前,计算机部门的工作人员过去常常按时下班,除非是在灭火或编写代码的时候.而现在,数据管理 ...
- SpringMVC一点简单地源码解析
. 1.1 init(初始化) 在第一次发出请求时,会调用HttpServletBean 的init()方法 org.springframework.web.servlet.HttpServletBe ...