共计 3052 个字符,预计需要花费 8 分钟才能阅读完成。
面试官:连 Serializable 都不晓得是什么,你这 5 年都干些什么了?
创誉代码
文 | 洪生鹏
https://baijiahao.baidu.com/s…
程序员面试时,序列化知识点常常会遇到。
张工是一名 java 程序员,工作 5 年了,始终从事 java 开发。最近到某互联网公司面试,做了口试题后,有一道口试题是这样子的:Serializable 有什么作用,张工没有作答,面谈时面试官又问了,张工答复不出个所以然。面试官:你都工作五年了,连序列化都不晓得,你这 5 年都干些什么了?张工一脸的无助,不过的确不应该,相似 Serializable 序列化这样的知识点,平时应该不会少用。
小编之前加入的口试也遇到了对于序列化的问题,对于序列化咱们都能晓得个大略,但要是能进一步剖析个所以然那就更好了,这样能给面试官留下更好的印象。
个别状况下,咱们在定义实体类时会继承 Serializable 接口,相似这样:
咱们在实体类中援用了 Serializable 这个接口,那么这个接口到底有什么?仔细的你会发现咱们还定义了个 serialVersionUID 变量。这个变量到底有什么作用?
什么是 Serializable 接口
一个对象序列化的接口,一个类只有实现了 Serializable 接口,它的对象能力被序列化。
什么是序列化?
序列化是将对象状态转换为可放弃或传输的格局的过程。与序列化绝对的是反序列化,它将流转换为对象。这两个过程联合起来,能够轻松地存储和传输数据。
为什么要序列化对象
把对象转换为字节序列的过程称为对象的序列化把字节序列复原为对象的过程称为对象的反序列化 什么状况下须要序列化?
当咱们须要把对象的状态信息通过网络进行传输,或者须要将对象的状态信息长久化,以便未来应用时都须要把对象进行序列化
那为什么还要继承 Serializable。那是存储对象在存储介质中,以便在下次应用的时候,能够很快捷的重建一个正本。
或者你会问,我在开发过程中,实体并没有实现序列化,但我同样能够将数据保留到 mysql、Oracle 数据库中,为什么非要序列化能力存储呢?
咱们来看看 Serializable 到底是什么,跟进去看一下,咱们发现 Serializable 接口外面居然什么都没有,只是个空接口
一个接口外面什么内容都没有,咱们能够将它了解成一个标识接口。
比方在课堂上有位学生遇到一个问题,于是举手向老师求教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,本人解决不了问题求教老师帮忙解决。在 Java 中的这个 Serializable 接口其实是给 jvm 看的,告诉 jvm,我不对这个类做序列化了,你 (jvm) 帮我序列化就好了。
Serializable 接口就是 Java 提供用来进行高效率的异地共享实例对象的机制,实现这个接口即可。
什么是 JVM?
JVM 是 Java Virtual Machine(Java 虚拟机)的缩写,JVM 是一种用于计算设施的标准,它是一个虚构进去的计算机,是通过在理论的计算机上仿真模仿各种计算机性能来实现的。
为什么要定义 serialversionUID 变量
简略看一下 Serializable 接口的阐明
从阐明中咱们能够看到,如果咱们没有本人申明一个 serialVersionUID 变量, 接口会默认生成一个 serialVersionUID
However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpectedInvalidClassException
s during deserialization.
然而强烈建议用户自定义一个 serialVersionUID, 因为默认的 serialVersinUID 对于 class 的细节十分敏感,反序列化时可能会导致 InvalidClassException 这个异样。
在后面咱们曾经新建了一个实体类 User 实现 Serializable 接口,并且定义了 serialVersionUID 变量。
咱们把 User 写到文件,而后读取进去。
是的,你没有看错,序列化与反序列化操作过程就是这么的简略。只须要将 User 写入到文件中,而后再从文件中进行复原,复原后失去的内容与之前齐全一样,然而两者是不同的对象。后面提到过一个问题,如果将 serialVersionUID 变量去掉,咱们来看看,会产生什么事件。
刚开始提到了,serialVersionUID 要不要指定呢?如果不指定会呈现什么样的结果?如果指定了当前后边的值又代表着什么意思呢?既然零碎指定了这个字段,那么必定是有它的作用的。
这个 serialVersionUID 是用来辅助对象的序列化与反序列化的,原则上序列化后的数据当中的 serialVersionUID 与以后类当中的 serialVersionUID 统一,那么该对象能力被反序列化胜利。这个 serialVersionUID 的具体的工作机制是:在序列化的时候零碎将 serialVersionUID 写入到序列化的文件中去,当反序列化的时候零碎会先去检测文件中的 serialVersionUID 是否跟以后的文件的 serialVersionUID 是否统一,如果始终则反序列化胜利,否则就阐明以后类跟序列化后的类产生了变动,比方是成员变量的数量或者是类型产生了变动,那么在反序列化时就会产生 crash,并且回报出谬误:
java.io.InvalidClassException: User; local class incompatible: stream classdesc serialVersionUID = -1451587475819212328, local class serialVersionUID = -3946714849072033140at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)at Main.readUser(Main.java:32)at Main.main(Main.java:10)
小编认为,相似序列化这样的基础知识,平时在学习中要器重,能力编写出更加高效稳固的程序。不知对此你是怎么对待的,欢送交换!