首页 课程 师资 教程 报名

程序员都在收藏的移动开发java面试题

  • 2019-08-15 14:25:48
  • 1911次 动力节点


image.png

  Java中的可序列化接口和可外部接口之间的区别是什么?

  下面是我的版本Externalizable给我们提供writeExternal()和readExternal()方法,这让我们灵活地控制Java序列化机制,而不是依赖于Java的默认序列化。正确实现Externalizable接口可以显著提高应用程序的性能。


  可序列化的方法有多少?如果没有方法,那么可序列化接口的用途是什么?


  可序列化Serializalbe接口存在于java.io包中,构成了Java序列化机制的核心。它没有任何方法,在Java中也称为标记接口。当类实现java.io.Serializable接口时,它将在Java中变得可序列化,并指示编译器使用Java序列化机制序列化此对象。


  什么是serialVersionUID?如果你不定义这个,会发生什么?


  serialVersionUID是一个privatestaticfinallong型ID,当它被印在对象上时,它通常是对象的哈希码,你可以使用serialver这个JDK工具来查看序列化对象的serialVersionUID。SerialVerionUID用于对象的版本控制。也可以在类文件中指定serialVersionUID。不指定serialVersionUID的后果是,当你添加或修改类中的任何字段时,则已序列化类将无法恢复,因为为新类和旧序列化对象生成的serialVersionUID将有所不同。


  序列化时,你希望某些成员不要序列化?你如何实现它?


  这也是一些时候也问,如什么是瞬态trasient变量,瞬态和静态变量会不会得到序列化等,所以,如果你不希望任何字段是对象的状态的一部分,然后声明它静态或瞬态根据你的需要,这样就不会是在Java序列化过程中被包含在内。


  如果类中的一个成员未实现可序列化接口,会发生什么情况?


  如果尝试序列化实现可序列化的类的对象,但该对象包含对不可序列化类的引用,则在运行时将引发不可序列化异常NotSerializableException,这就是为什么我始终将一个可序列化警报(在我的代码注释部分中),代码注释最佳实践之一,指示开发人员记住这一事实,在可序列化类中添加新字段时要注意。


  如果类是可序列化的,但其超类不是,则反序列化后从超级类继承的实例变量的状态如何?


  Java序列化过程仅在对象层次都是可序列化结构中继续,即实现Java中的可序列化接口,并且从超级类继承的实例变量的值将通过调用构造函数初始化,在反序列化过程中不可序列化的超级类。一旦构造函数链接将启动,就不可能停止,因此,即使层次结构中较高的类实现可序列化接口,也将执行构造函数。


  是否可以自定义序列化过程,或者是否可以覆盖Java中的默认序列化过程?


  答案是肯定的,你可以。对于序列化一个对象需调用ObjectOutputStream.writeObject(saveThisObject),并用ObjectInputStream.readObject()读取对象,但Java虚拟机为你提供的还有一件事,是定义这两个方法。如果在类中定义这两种方法,则JVM将调用这两种方法,而不是应用默认序列化机制。你可以在此处通过执行任何类型的预处理或后处理任务来自定义对象序列化和反序列化的行为。


  需要注意的重要一点是要声明这些方法为私有方法,以避免被继承、重写或重载。由于只有Java虚拟机可以调用类的私有方法,你的类的完整性会得到保留,并且Java序列化将正常工作。在我看来,这是在任何Java序列化面试中可以问的最好问题之一,一个很好的后续问题是,为什么要为你的对象提供自定义序列化表单?

image.png

  假设新类的超级类实现可序列化接口,如何避免新类被序列化?


  如果类的Super类已经在Java中实现了可序列化接口,那么它在Java中已经可以序列化,因为你不能取消接口,它不可能真正使它无法序列化类,但是有一种方法可以避免新类序列化。为了避免Java序列化,你需要在类中实现writeObject()和readObject()方法,并且需要从该方法引发不序列化异常NotSerializableException。这是自定义Java序列化过程的另一个好处,如上述序列化面试问题中所述,并且通常随着面试进度,它作为后续问题提出。


  在Java中的序列化和反序列化过程中使用哪些方法?


  在序列化基本上面试官试图知道:你是否熟悉readObject()的用法、writeObject()、readExternal()和writeExternal()。Java序列化由java.io.ObjectOutputStream类完成。该类是一个筛选器流,它封装在较低级别的字节流中,以处理序列化机制。要通过序列化机制存储任何对象,我们调用ObjectOutputStream.writeObject(savethisobject),并反序列化该对象,我们称之为ObjectInputStream.readObject()方法。调用以writeObject()方法在java中触发序列化过程。关于readObject()方法,需要注意的一点很重要一点是,它用于从持久性读取字节,并从这些字节创建对象,并返回一个对象,该对象需要类型强制转换为正确的类型。


  假设你有一个类,它序列化并存储在持久性中,然后修改了该类以添加新字段。如果对已序列化的对象进行反序列化,会发生什么情况?


  这取决于类是否具有其自己的serialVersionUID。正如我们从上面的问题知道,如果我们不提供serialVersionUID,则Java编译器将生成它,通常它等于对象的哈希代码。通过添加任何新字段,有可能为该类新版本生成的新serialVersionUID与已序列化的对象不同,在这种情况下,Java序列化API将引发java.io.InvalidClassException,因此建议在代码中拥有自己的serialVersionUID,并确保在单个类中始终保持不变。


  Java序列化机制中的兼容更改和不兼容更改是什么?


  真正的挑战在于通过添加任何字段、方法或删除任何字段或方法来更改类结构,方法是使用已序列化的对象。根据Java序列化规范,添加任何字段或方法都面临兼容的更改和更改类层次结构或取消实现的可序列化接口,有些接口在非兼容更改下。对于兼容和非兼容更改的完整列表,我建议阅读Java序列化规范。


  我们可以通过网络传输一个序列化的对象吗?


  是的,你可以通过网络传输序列化对象,因为Java序列化对象仍以字节的形式保留,字节可以通过网络发送。你还可以将序列化对象存储在磁盘或数据库中作为Blob。


  在Java序列化期间,哪些变量未序列化?


  这个问题问得不同,但目的还是一样的,Java开发人员是否知道静态和瞬态变量的细节。由于静态变量属于类,而不是对象,因此它们不是对象状态的一部分,因此在Java序列化过程中不会保存它们。由于Java序列化仅保留对象的状态,而不是对象本身。瞬态变量也不包含在Java序列化过程中,并且不是对象的序列化状态的一部分。在提出这个问题之后,面试官会询问后续内容,如果你不存储这些变量的值,那么一旦对这些对象进行反序列化并重新创建这些变量,这些变量的价值是多少?这是你们要考虑的。


选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交