首页 课程 师资 教程 报名

最新java面试题及答案整理

  • 2020-02-06 10:25:45
  • 2270次 动力节点


  为什么等待和通知是在Object类而不是Thread中声明的?


  一个棘手的Java问题,如果Java编程语言不是你设计的,你怎么能回答这个问题呢。Java编程的常识和深入了解有助于回答这种棘手的Java核心方面的面试问题。


  为什么wait,notify和notifyAll是在Object类中定义的而不是在Thread类中定义


  这是有名的Java面试问题,招2~4年经验的到高级Java开发人员面试都可能碰到。


  这个问题的好在它能反映了面试者对等待通知机制的了解,以及他对此主题的理解是否明确。就像为什么Java中不支持多继承或者为什么String在Java中是final的问题一样,这个问题也可能有多个答案。


  为什么在Object类中定义wait和notify方法,每个人都能说出一些理由。从我的面试经验来看,wait和nofity仍然是大多数Java程序员最困惑的,特别是2到3年的开发人员,如果他们要求使用wait和notify,他们会很困惑。因此,如果你去参加Java面试,请确保对wait和notify机制有充分的了解,并且可以轻松地使用wait来编写代码,并通过生产者-消费者问题或实现阻塞队列等了解通知的机制。


  为什么等待和通知需要从同步块或方法中调用,以及Java中的wait,sleep和yield方法之间的差异,如果你还没有读过,你会觉得有趣。为何wait,notify和notifyAll属于Object类?为什么它们不应该在Thread类中?以下是我认为有意义的一些想法:


  1)wait和notify不仅仅是普通方法或同步工具,更重要的是它们是Java中两个线程之间的通信机制。对语言设计者而言,如果不能通过Java关键字(例如synchronized)实现通信此机制,同时又要确保这个机制对每个对象可用,那么Object类则是的正确声明位置。记住同步和等待通知是两个不同的领域,不要把它们看成是相同的或相关的。同步是提供互斥并确保Java类的线程安全,而wait和notify是两个线程之间的通信机制。


  2)每个对象都可上锁,这是在Object类而不是Thread类中声明wait和notify的另一个原因。


  3)在Java中为了进入代码的临界区,线程需要锁定并等待锁定,他们不知道哪些线程持有锁,而只是知道锁被某个线程持有,并且他们应该等待取得锁,而不是去了解哪个线程在同步块内,并请求它们释放锁定。


  4)Java是基于Hoare的监视器的思想。在Java中,所有对象都有一个监视器。


  线程在监视器上等待,为执行等待,我们需要2个参数:


  一个线程


  一个监视器(任何对象)


  在Java设计中,线程不能被指定,它总是运行当前代码的线程。但是,我们可以指定监视器(这是我们称之为等待的对象)。这是一个很好的设计,因为如果我们可以让任何其他线程在所需的监视器上等待,这将导致“入侵”,导致在设计并发程序时会遇到困难。请记住,在Java中,所有在另一个线程的执行中侵入的操作都被弃用了(例如stop方法)。


  如果你的Serializable类包含一个不可序列化的成员,会发生什么?你是如何解决的?


  任何序列化该类的尝试都会因NotSerializableException而失败,但这可以通过在Java中为static设置瞬态(trancient)变量来轻松解决。


  Java序列化相关的常见问题


  Java序列化是一个重要概念,但它很少用作持久性解决方案,开发人员大多忽略了Java序列化API。根据我的经验,Java序列化在任何Java核心内容面试中都是一个相当重要的话题,在几乎所有的网面试中,我都遇到过一两个Java序列化问题,我看过一次面试,在问几个关于序列化的问题之后候选人开始感到不自在,因为缺乏这方面的经验。


  他们不知道如何在Java中序列化对象,或者他们不熟悉任何Java示例来解释序列化,忘记了诸如序列化在Java中如何工作,什么是标记接口,标记接口的目的是什么,瞬态变量和可变变量之间的差异,可序列化接口具有多少种方法,在Java中,Serializable和Externalizable有什么区别,或者在引入注解之后,为什么不用@Serializable注解或替换Serializalbe接口。


  最新java面试题及答案整理


  在本文中,我们将从初学者和高级别进行提问,这对新手和具有多年Java开发经验的高级开发人员同样有益。


  关于Java序列化的10个面试问题


  大多数商业项目使用数据库或内存映射文件或只是普通文件,来满足持久性要求,只有很少的项目依赖于Java中的序列化过程。无论如何,这篇文章不是Java序列化教程或如何序列化在Java的对象,但有关序列化机制和序列化API的面试问题,这是值得去任何Java面试前先看看以免让一些未知的内容惊到自己。


  对于那些不熟悉Java序列化的人,Java序列化是用来通过将对象的状态存储到带有.ser扩展名的文件来序列化Java中的对象的过程,并且可以通过这个文件恢复重建Java对象状态,这个逆过程称为deserialization。


  什么是Java序列化


  序列化是把对象改成可以存到磁盘或通过网络发送到其他运行中的Java虚拟机的二进制格式的过程,并可以通过反序列化恢复对象状态.Java序列化API给开发人员提供了一个标准机制,通过java.io.Serializable和java.io.Externalizable接口,ObjectInputStream及ObjectOutputStream处理对象序列化.Java程序员可自由选择基于类结构的标准序列化或是他们自定义的二进制格式,通常认为后者才是最佳实践,因为序列化的二进制文件格式成为类输出API的一部分,可能破坏Java中私有和包可见的属性的封装.


  如何序列化


  让Java中的类可以序列化很简单.你的Java类只需要实现java.io.Serializable接口,JVM就会把Object对象按默认格式序列化.让一个类是可序列化的需要有意为之.类可序列会可能为是一个长期代价,可能会因此而限制你修改或改变其实现.当你通过实现添加接口来更改类的结构时,添加或删除任何字段可能会破坏默认序列化,这可以通过自定义二进制格式使不兼容的可能性最小化,但仍需要大量的努力来确保向后兼容性。序列化如何限制你更改类的能力的一个示例是SerialVersionUID。


  如果不显式声明SerialVersionUID,则JVM会根据类结构生成其结构,该结构依赖于类实现接口和可能更改的其他几个因素。假设你新版本的类文件实现的另一个接口,JVM将生成一个不同的SerialVersionUID的,当你尝试加载旧版本的程序序列化的旧对象时,你将获得无效类异常InvalidClassException。


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


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


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


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


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


  我最喜欢的关于Java序列化的问题面试问题之一。serialVersionUID是一个privatestaticfinallong型ID,当它被印在对象上时,它通常是对象的哈希码,你可以使用serialver这个JDK工具来查看序列化对象的serialVersionUID。SerialVerionUID用于对象的版本控制。也可以在类文件中指定serialVersionUID。不指定serialVersionUID的后果是,当你添加或修改类中的任何字段时,则已序列化类将无法恢复,因为为新类和旧序列化对象生成的serialVersionUID将有所不同。Java序列化过程依赖于正确的序列化对象恢复状态的,,并在序列化对象序列版本不匹配的情况下引发java.io.InvalidClassException无效类异常,了解有关serialVersionUID详细信息,请参阅这篇文章,需要FQ。


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


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


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


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


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


  Java序列化过程仅在对象层次都是可序列化结构中继续,即实现Java中的可序列化接口,并且从超级类继承的实例变量的值将通过调用构造函数初始化,在反序列化过程中不可序列化的超级类。一旦构造函数链接将启动,就不可能停止,因此,即使层次结构中较高的类实现可序列化接口,也将执行构造函数。正如你从陈述中看到的,这个序列化面试问题看起来非常棘手和有难度,但如果你熟悉关键概念,则并不难。


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


最新java面试题及答案整理


      以上就是动力节点Java培训机构小编介绍的“最新java面试题及答案整理”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。


相关推荐


最新最全java面试题及答案(初级到高级)


史上最全的中高级JAVA工程师面试题及答案汇总


Java高级开发工程师面试题


2019史上最全java面试题题库大全800题


哪有资深java工程师面试题


选你想看

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

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

先测评确定适合在学习

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