面试官:连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 unexpectedInvalidClassExceptions 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)

小编认为,相似序列化这样的基础知识,平时在学习中要器重,能力编写出更加高效稳固的程序。不知对此你是怎么对待的,欢送交换!