Java面试题解构
有次一个同事让我一同去面试一个候选人,没仔细看简历,所以在问了设计模式之后就让他谈一谈对内存泄漏和垃圾回收的理解,当时候选人一下子就懵了。后来才知道,他面的是初、中级开发职位,想来估计候选人心里也在骂我吧。
我自己用过各式各样的方法面试候选人,也被各式各样的方式面试过。有让拿电脑直接写代码的,有让在白板上写思路、画结构的,或者挨个知识点问问题的。面试,应该是要测试候选人「是否有做好某些事情的能力」,而不应该是「知道某些事情的能力」。虽然这两者往往是相关的,但有很大一部分问题却是对「把事情做好」没有任何帮助的。其中的一类是那些「你不用的时候只是大概知道,需要使用的时候花一分钟就可以搞清楚」的问题,就算你是一个比较好学的开发者,平时会看一些跟工作关系不是那么大的东西,并且可以搞得很清楚,但时间一长,再去问你细节,我想同样会模糊不清,甚至会出错。
本文并不是面试刷题的题库。而是希望可以通过对面试的问题进行分类,帮助Java工程师在准备面试时,可以高屋建瓴,快速找到所需的知识点。同时会给出一些好的、坏的示例,希望可以帮助到一些人。
面试问题的分类
关于会被问到的Java方面的问题,大致可以分为以下几类:
1. Hotspot VM(Runtime、GC、JIT)相关问题
这些问题其实属于要了解的东西,对指导编码、问题排查、运行时逻辑的理解都有好处。
但如果非要问你G1、CMS、Serial垃圾回收器各自的实现方法及其不同,除非你面的就是做JVM调优的职位,那你也是倒了霉了,解决方案只能是面试前突击巩固这方面的知识。
2. JDK中特定类的使用问题
如果你的工作会用到一些类,可能你会很熟悉,但老实说,还是会有很多类用了很多次,每次都要去源码里看注释的情况……
有注释为毛要浪费珍贵的脑容量。有病
3. JDK中特定类(或操作符、关键字)的实现问题
相信很大一部分(有工作经验的)工程师的工作内容是不需要考虑这些问题的,但很多有追求的工程师都很乐意去探索这些问题,比如HashMap
的实现原理,TransferQueue
的算法逻辑。
但是,那么多类,谁能保证全部记得很清楚,如果有,一定是来面试前背过了。
4. 其他一些变态的陷阱问题
各种乱花渐欲迷人眼的问题,如「重载和重写的区别」「final、finally、finalize的区别」之流,实在无力吐槽。出这些题的人估计是想要考察你的基本功,但又怀着不耐烦的心情,所以挖个坑看你怎么跳。
有种你编程不用搜索引擎啊。
这里换个姿势问,面试官的逼格立马就显现了。比如「JDK如何保证在try-catch-finally中的finally块一定会被执行的?」,但这就属于第3类问题了,如果回答不出来,应该引导他通过已有的知识和自己的想法去实现。
5. 解决实际问题
这是真正有价值的问题,可以考察人的思维及解决问题能力的问题。而且不论是业务相关,亦或是技术理论相关的,都可以问出有价值的问题。
如「自己设计一个ArrayList
/LinkedBlockingQueue
」,「设计一个秒杀系统」,「如果碰到XXX问题,你估计是哪里出的问题」等等。
6. 与Java无关的问题
这种问题通常是为了考察应聘者的性格、人品、知识面、学习能力等,比如「简单描述一下HTTPS的工作流程」、「最近是否有在看书或者哪方面的知识」等。有些有套路,可以抱抱佛脚,通过刷题刷出来。其他的只能自求多福了。
相关问题示例
下面是一些从网上看到或者自己被问到过的一些问题,仅供参考。
第一类问题
1. 简单描述一下JVM的GC
A:随意发挥……可以参考Java 9中的GC调优基础
这是一个典型的比较有开放性的问题,面试者可以从自己了解的方面入手,如分代、运行时内存结构。如果对垃圾回收器比较了解,那更可以侃侃而谈。
如果被问到了比较有针对性的问题,那就看你面试前的课补的好不好了。
2. Java中有哪些多线程同步的手段
这个问题也可以延伸出很多知识,synchronized
的实现原理、synchronized
中的锁膨胀、为什么有时候使用volatile
可以带来更好的性能、悲观锁&乐观锁的概念、新一代的基于Lock
的锁机制,更甚者可能会问到Java的内存模型(JMM)。
第二类问题
1. StringBuilder
vs StringBuffer
A:前者是后者不加锁的版本,使用场景BlaBla……
现在还有人问这个问题,只有两种可能:1. 面试官或者候选人的水平比较初级;2. 面试官一下子想不到别的好问的。
2. Java8比Java7添加了什么新的特性
A:Lambda、streams、接口默认方法……
我要是背书背的好早学文科了。
3. Java自带线程池判断线程池是否已经结束运行的方法叫什么
A:isShutdown和isTerminated。
4. BlockingQueue
,CountDownLatch
及Semeaphore
的使用场景
5. java.util.Date
与java.sql.Date
有什么区别
A:继承关系
不知道这个问题的意义在哪里。
6. 如果要从LinkedBlockingQueue
中取出头部对象,分别哪个方法会返回null、抛错、阻塞
A:take - 阻塞,poll - 返回null,remove - 抛错
第三类问题
1. ThreadLocal
的实现原理
A:就是一个只有当前线程可访问的以ThreadLocal
实例为Key的HashMap
,其内部的Map实现和HashMap
的实现差不多,这个Map的实例存储在Thread
对象上,所以通过封装,能保证线程只访问自己的ThreadLocal
变量。
好吧,很可能面试官想听到的就是这样一句话。
但ThreadLocal之所以重要其实是其背后的设计思想,它将变量从共享的和需要多线程同步的环境转移到了线程私有和不需要同步的环境内,这种思想可以用来解决很多不同的场景下的问题。
但是,谁关心这些呢?
2. LinkedList
的实现原理
A:它是一个双向列表,实现了List
、Deque
、Cloneable
等接口
老实说,Deque
(双向队列)这个东西见过几次,但没用过,所以现在也说不太清楚它的特征和实际使用场景,所以也不想胡侃。
3. ConcurrentHashMap
的实现原理
A:它是一个对写操作加了锁的HashMap
,不同的是它做了二次分割,元素被存储在不同的桶里,以见效锁的数据范围,提升性能。
在JDK8中对这种实现又进行了修改,JDK8中的ConcurrentHashmap
基于CAS和TreeBin
实现的,不需要对segment或者全局加锁,只需要对单行枷锁(hashCode相同),后边的链表是链表加红黑树。对于单个值的修改使用CAS。
面试官很可能想听到的是这样,但这里重要的是分治的概念。其实完全可以让候选人尝试自己去设计一个ConcurrentHashMap
,然后引导他去拆分HashMap
,这样才是正道啊。
4. hashcode()
和equals()
的关系
A:根据JVM标准,equals()
相等的对象,hashcode()
应该永远相对,反之则不一定,详见HashMap
的实现。
这个问题其实挺好的,但如果只是简单的问一下,没有任何意义,仍然考的是记忆力。
5. TransferQueue
的算法是什么样的,它和BlockingQueue
有哪些不同
A:源代码里有。
这么回答肯定是不好的,还是去补补课吧。如果你觉得面试官问这个太无聊,可以拿到offer后丑拒。
第五类问题
1. 用 wait-notify 写一段代码来解决生产者-消费者问题,更进一步,在分布式的环境下怎么解决
A:哈哈哈,我们来写段代码吧……
wait()
和notify()
都是线程间通信的方法,可以直接对线程的行为进行操作。他们的本质其实是传递生产者-消费者各自的消息,理解了这一点,那么在分布式环境下就很简单了,只要找到一个第三方的可以用来传递消息的媒介(Zookeeper、Redis、Kafka等)就可以了。
2. 设计一个线程池
A:可以参考Java线程池的理论与实践
如果对JDK的线程池java.util.concurrent.ThreadPoolExecutor
比较了解,可以把一些简单的特性放上去。如果不了解,可以直接设计一个线程数组,然后加一些业务逻辑。所谓线程池,基本也就如此。
3. 设计一个IOC容器
A:用反射,注解,还有IOC的理论
第六类问题
1. 谈谈你对C10K问题的理解
A:NIO对BIO在吞吐量上的优势,可以参考从I/O模型到Netty(一)
我有一个微信公众号,经常会分享一些Java技术相关的干货;如果你喜欢我的分享,可以用微信搜索“Java团长”或者“javatuanzhang”关注。