Java后端面试必看:40道5星高频题与追问链深度解析
这几年我面过不少人也被面过很多次。说实话“八股文”这三个字在技术圈里一直被调侃很多人觉得面试官只会拿着背好的题来考人。但我自己坐在面试官那一侧之后才慢慢意识到一个事实大部分挂掉的候选人不是输在“题没背熟”而是输在根本不知道题目背后要考察什么。这份“40道5⭐题”不是我在网上随便扒一份面经汇总起来的。它来自我这两年做技术面试官留下的高频题目记录也参考了很多一线公司的真实面试反馈。既然要聊八股文那咱们就用从业者的方式把它聊透这40道题为什么能评上5星每一道题背后藏着哪些追问现场怎么回答才不显得像背课文。如果你正在准备Java后端方向的面试这篇文章可以直接当备考清单用如果你面C、嵌入式或者前端也可以借这套思路去补自己方向的知识地图原理是通用的。1. 这份40道5⭐题是怎么筛出来的1.1 我的筛选标准不是所有面试题都能叫5⭐先解释一下“5⭐”在我这里的定义。它不代表题目本身难到让人写不出来而代表三个维度的综合评分出题频率高、追问空间深、答不好基本影响面试结论。我见过很多人准备面试喜欢搞题海战术一本几百页的面经从头啃到尾。可实际效果往往很差因为大部分题在真实面试里出现的概率极低。真正有经验的面试官不会漫无目的地问一堆零散问题他脑子里通常有一条完整的考察主线语言基础怎么样、并发和内存模型懂不懂、数据库索引有没有实战感觉、框架原理是不是只停留在会用。所以这40道题是按照一条“后端工程师知识闭环”来组织的。从Java基础与集合、JVM内存与GC、并发编程到MySQL索引与事务、Spring核心机制再到网络协议和Redis实战场景每一步之间都有承接关系。它虽然不是一份覆盖所有考点的全量题库但如果你能把这份清单上的题都答得有条理已经足够支撑你通过绝大多数初中级岗位的技术面。另外要说明一点这份清单是按Java后端方向整理的。程序员圈子里的“八股文”确实每个方向都有C有C的八股嵌入式有嵌入式的八股前端也有自己的八股。但不管哪个方向底层的准备逻辑是一致的无非就是“语言核心机制 内存模型 并发模型 常用框架/中间件原理 业务场景设计”这几大块。我的建议是先把这套整理方法吃透再往自己方向去平移。1.2 40道题全景清单先别翻答案试着自测一遍下面这40道题我按模块分组列出来。“5⭐理由”那一栏是给面试官视角的提示也是你复习时的侧重点。建议你先自己过一遍能流畅说出思路的打勾说不出来的做标记后面复习就有针对性了。模块题号题目5⭐理由Java基础与集合1String、StringBuilder、StringBuffer区别String为什么不可变语言基础高频题能引出常量池、线程安全、不可变对象设计Java基础与集合2和equals的区别hashCode与equals的约定几乎每场必问考察对象语义理解Java基础与集合3ArrayList和LinkedList区别ArrayList扩容机制集合底层结构追问空间大Java基础与集合4HashMap底层结构put流程为什么链表转红黑树阈值是8八股文中的“题眼”最容易拉开差距Java基础与集合5ConcurrentHashMap在JDK7和JDK8中的实现差异考察并发集合演进思路Java基础与集合6异常体系结构受检异常和非受检异常怎么区分看似简单很多人答不清Java基础与集合7Java泛型机制和类型擦除考语言原理深度Java基础与集合8serialVersionUID的作用是什么序列化细节实战中踩坑多JVM与内存9JVM运行时数据区域哪些区域会OOMJVM必考也是排查问题的基础JVM与内存10如何判断对象可回收GC Roots有哪些GC前置知识追问多JVM与内存11常见垃圾收集器CMS和G1的区别高频中的高频需要能对比说明JVM与内存12类加载过程为什么要双亲委派考JVM底层设计思想JVM与内存13强引用、软引用、弱引用、虚引用区别结合内存泄漏场景常考JVM与内存14线上OOM怎么排查实战题有项目经验的人答得明显更好并发编程15synchronized原理锁升级过程并发基础中的核心并发编程16volatile作用和synchronized区别高频追问考察对JMM的理解并发编程17CAS原理ABA问题怎么解决无锁并发思想容易追问并发编程18AQS是什么基于AQS实现了哪些组件大厂高频能区分“会用”和“懂原理”并发编程19ThreadLocal原理为什么会有内存泄漏实战中经常用错面试官爱问并发编程20线程池核心参数执行流程核心线程数怎么设置五星中的五星几乎必考并发编程21JMM是什么如何理解可见性、原子性、有序性并发编程的基石MySQL22一条SQL查询从客户端到返回结果经历了什么考察MySQL整体架构MySQL23B树索引结构为什么MySQL用它而不用哈希或B树索引原理核心题MySQL24联合索引最左前缀怎么理解哪些情况会导致索引失效实战调优最常见问题MySQL25事务的ACID和隔离级别MySQL默认隔离级别是什么事务基础必考MySQL26MVCC是什么通过什么机制实现考察InnoDB事务隔离底层逻辑MySQL27数据库有哪些锁什么是间隙锁并发写场景问得深Spring28什么是IoC什么是AOP它们解决什么问题Spring设计思想的入口Spring29Spring Bean的生命周期看你是不是真的读过源码Spring30Spring事务传播行为有哪些失效场景实际开发高频踩坑点Spring31Spring如何解决循环依赖为什么需要三级缓存源码级问题区分度极高Spring32MyBatis中#{}和${}的区别日常开发细节涉及SQL注入网络协议33TCP三次握手过程为什么不是两次经典但很多人只背结论网络协议34TCP四次挥手TIME_WAIT为什么存在高频网络题能串联线上问题网络协议35HTTP和HTTPS的区别HTTPS握手流程前后端都会问网络协议36TCP和UDP的区别TCP如何保证可靠性网络基础容易追问拥塞控制Redis与场景题37Redis为什么快有哪些底层数据结构Redis必考题Redis与场景题38RDB和AOF持久化优缺点考数据可靠性的权衡Redis与场景题39缓存穿透、击穿、雪崩怎么区分和解决场景题区分度很高Redis与场景题40怎么用Redis实现分布式锁要注意什么分布式场景高频题坑很多2. 面试官为什么爱问八股文一道题背后的三层意图2.1 第一层意图用最低成本筛掉没准备的人先说实话基础题确实是最容易被“背”出来的但它依然有效的原因在于它能把“完全没准备的人”和“准备好了但深度不够的人”快速分开。有一次我面一个简历上写了三年经验的候选人问HashMap的put流程。他支支吾吾说“先算hash放进去冲突就链表”再追问“链表什么时候转红黑树”他沉默了十几秒。技术面试的时间通常只有30到60分钟如果连这种高频基础题都答不完整面试官很难有理由相信他在项目中真的深入思考过技术方案。基础八股题承担的角色就是第一轮漏斗。你听到别人说“外包怎么全是八股文”“面试全是八股文”本质上是因为这个漏斗在大多数公司都存在只是不同公司过滤的松紧程度不一样。别抱怨这个机制不合理。只要你把基础原理理解透这层漏斗对你来说就不是压力反而是你展示自己的第一个舞台。2.2 第二层意图通过追问看你是“背答案”还是“懂原理”真正让八股文发挥区分作用的不是第一问而是第二问、第三问。比如面试官问volatile常规答法就是“保证可见性防止指令重排”。这个回答本身没错但也就值60分。有经验的面试官马上会追问volatile是如何保证可见性的底层是内存屏障还是lock前缀写操作时发生了什么读操作时又发生了什么它能不能保证原子性为什么如果你只背过答案到这里基本就会卡住。但如果你真的理解JMM、理解缓存一致性协议、理解编译器指令重排就算记不住x86汇编指令的具体名称也能把逻辑链路讲顺。这也是我为什么在这份清单里区分“5⭐题”而不是让你去背具体知识点。5⭐题不是用来背的是用来“被追问”的。真正能拉开差距的永远是追问环节。2.3 第三层意图看你能否把基础原理映射到真实业务场景八股文的终点不是背题本身而是看你能不能把题里的知识用到项目里。所以你会发现现在很多面试官问完基础题后会紧跟一个场景题比如“如果线上接口突然变慢你怎么排查”或者“你们的缓存遇到过雪崩吗”这其实是八股题在场景里的延伸。比如Redis的缓存击穿、穿透、雪崩那几道题如果你只是背下了“空值缓存、布隆过滤器、互斥锁”这些名词但说不清楚自己的业务到底适合哪种方案、方案的代价是什么那面试官依然会给你打低分。反过来说如果你能把基础原理和项目经历串起来比如“我们用Redis缓存商品详情大促时某个热点key过期导致数据库压力上升后来通过逻辑过期异步刷新解决”这就不再是背八股文而是展示工程判断力。这也是你准备所有八股题时的最终目标。3. 五道五星级的追问链拆解从标准答案到答题思路3.1 HashMap从put流程到泊松分布再到并发问题HashMap是我面试时必问的一道题不是因为它多难而是因为它的追问链太顺滑了。只要候选人能答出“数组链表红黑树”我就能一路往下问hash怎么计算、为什么容量是2的幂、扩容怎么迁移、负载因子为什么是0.75、链表长度为8是怎么定出来的、JDK8在并发下会出什么问题、ConcurrentHashMap是怎么解决的。先说主体回答路径。JDK8的HashMap底层是数组加链表加红黑树。put的时候先对key的hashCode做扰动然后通过(n-1)hash定位到数组下标如果该位置是空的就放进去如果已经有元素就用equals比较key相同则覆盖valuekey不同则追加到链表尾部链表长度超过8且数组容量达到64时转成红黑树。面试官追问“为什么超过8才转红黑树”标准说法是泊松分布概率极低在负载因子0.75的情况下链表长度到达8的概率只有约千万分之几。这个答案能体现你读过源码注释。但更进一步的回答是树节点比普通链表节点占用的内存大约多一倍所以在数据量不大时链表更省内存红黑树是为了防极端哈希冲突导致查询退化成O(n)。这个补充能说明你不只是记住了数字还理解了这样设计的工程考量。再往下面试官很可能会追问“为什么扩容是2倍为什么数组容量要设计成2的幂”。因为HashMap取下标用的是(n-1)hash这个位运算比取模高效而且只有当n是2的幂时n-1的二进制定是低位全是1才能等价于hash对n取模。扩容时元素要么留在原位要么移动到“原位置oldCap”这是JDK8优化过的扩容算法不需要重新计算每个key的hash。这道题完全值得你花半小时画图推演。建议你把一个初始容量16的HashMap模拟put 20个key的流程画出来再把链表树化的条件写一遍。能画出来才算真的会。3.2 线程池不能只背参数要会“调参”线程池这道题几乎每场Java面试都会出现。我见到太多候选人能熟练背出七大参数但被问到“你项目里的线程池核心线程数怎么定的”就沉默了。所以这道题你一定要把“给一个具体场景调参”的能力准备好。先理清执行流程这是基本功。提交一个任务后当前工作线程数小于核心线程数直接创建核心线程执行大于等于核心线程数尝试把任务放入阻塞队列队列满了且当前线程数小于最大线程数就创建非核心线程执行队列满了而且线程数已经达到maximumPoolSize就执行拒绝策略。参数设置部分网上流传最广的口径是CPU密集型设N1IO密集型设2N。这个公式可以当入门参考但不能死背。更好的思考方式是先判断任务属于计算型还是等待型。假设一个任务90%的时间在等待下游HTTP接口响应或数据库查询10%的时间在做CPU计算那线程数可以相对调大一些让CPU尽量别闲着。反过来如果任务全是CPU运算线程数超过CPU核心数反而会因上下文切换降低吞吐。我你一个真实案例。有一次同事写了一个线程池corePoolSize设的是2maxPoolSize设的是10阻塞队列用的是无界的LinkedBlockingQueue。看起来配置没问题但上线后被调用方疯狂超时。排查半天发现无界队列意味着队列永远不会满所以线程数永远只维持在2后面来的9999个任务全在排队。这就是没有理解“core线程满了先入队队列满了才创建新线程”的执行顺序导致的。所以我在生产环境通常建议用有界队列把队列容量当成一个真实的背压阈值触发拒绝策略时再考虑告警或者降级。拒绝策略方面CallerRunsPolicy在某些场景下很实用因为它把任务回退给提交线程执行天然起到限流作用。现场回答这道题时建议按三条走先说执行流程再说参数估算思路最后带上你项目里的真实配置和理由。能说到这一层面试官基本不会再往深追问。3.3 MySQL索引失效一条慢SQL带你找到真相索引相关的问题有很强的实战属性。很多候选人清楚B树的结构但一给具体SQL就判断不了索引会不会失效。MySQL这一块比起死背B树面试官更想看到的其实是面对一条慢SQL你知不知道问题出在哪里。我给你一套“三步判断法”应付大多数索引题都够用。第一步看WHERE条件里有没有违反最左前缀第二步看WHERE条件里有没有对索引列做函数运算、隐式类型转换或LIKE前缀模糊第三步看排序和分组有没有吃上索引。来一个具体例子。假设有一张订单表建了一个联合索引(user_id, status, create_time)。面试官问下面这条SQL会不会走索引select * from orders where status paid order by create_time desc limit 20答案是不会至少不会走这个联合索引。原因很简单B树联合索引先按user_id排序再按status排序再按create_time排序。你跳过了user_id这个最左列直接从status开始过滤优化器没办法有效利用这个索引的有序性只能做全表扫描然后再排序。这就是最左前缀原则的本质。再看一个高频考点范围条件。比如where user_id 100 and status 0这个条件下MySQL最多只能用到联合索引里的user_id和status两列create_time索引列就废了。因为status是范围条件范围右边的索引列无法继续用于精确定位。这一点常被拿来和“status paid”这种等值条件做对比因为等值条件右边的列仍然可以继续走索引。还有隐式类型转换经典案例就是user_id字段在表里是varchar类型但SQL里写成了where user_id 123。MySQL可能对user_id这列做了隐式CAST导致索引列上发生了函数操作索引失效。你在准备这些细节时不要只看结论而是要能解释“为什么”面试官追问一个“为什么”你就不慌了。3.4 Spring循环依赖从三级缓存到AOP代理Spring的循环依赖是一道很有区分度的源码级八股。如果你只背出“三级缓存”几个字没有把对象创建的步骤讲清楚很容易被当成背题选手。先说基础。Spring创建Bean大致分三步实例化、填充属性、初始化。所谓循环依赖就是A里注入了BB里又注入了A。假如A先开始创建执行完实例化之后Spring会把这个早期对象放入三级缓存然后进入填充属性阶段。此时发现需要注入B于是去创建B。B也需要注入A它从三级缓存里找到了A的早期引用于是成功完成B的创建。B创建完A继续填充属性拿到B最后也完成创建。面试官追问“为什么一定要三级缓存二级不行吗”这里才是真正的分水岭。二级缓存能保存早期引用但在没有完全创建好的对象上AOP代理不一定能提前生成。三级缓存里存的是一个ObjectFactorySpring在getEarlyBeanReference环节会判断这个Bean是否需要进行AOP代理如果需要就在这个环节把代理对象提前暴露出去。所以三级缓存本质上是把“引用的提前暴露”和“AOP代理的生成时机”做了一个解耦。如果只有两级缓存要提前生成代理对象就得在实例化后就立即判断是否需要AOP这会破坏很多代理创建的灵活性。再补充一个高频追问构造器循环依赖为什么解决不了因为构造器注入要求对象在构造阶段就拿到完整依赖而早期引用此时对应的对象还没有填充属性无法安全注入所以Spring默认解决不了。如果遇到这个问题常规解法是改成setter注入或者加Lazy打破依赖链。这道题准备的建议是不要只记“三级缓存”这个名词而是把Bean生命周期完整地串一遍。能说出来“先实例化再暴露早期引用到三级缓存再填充属性再初始化并放入一级缓存”即使记不住每个缓存的Map名称面试官也会觉得你是懂原理的。3.5 Redis三兄弟缓存穿透、击穿、雪崩的实战分水岭缓存穿透、缓存击穿、缓存雪崩这三兄弟几乎和“你怎么保证缓存和数据库一致性”并列成为Redis部分的必考题。很多人能分清定义但一到“你的项目里怎么解决”就露馅。穿透是指请求了一个缓存和数据库里都不存在的数据。比如你用用户ID查用户信息黑客故意传一个不存在的ID每次请求都直接打到数据库。常规方案是缓存空值给一个较短的TTL让后续相同请求直接命中空缓存另一个方案是布隆过滤器用很低的成本过滤掉不存在的数据。需要注意的是这两种方案不是二选一。布隆过滤器会有误判意思是有可能存在的数据被它拦住了吗不会它只会把不存在的数据误判为可能存在所以它适合那种数据总量相对固定、能接受一次性过滤器的场景。击穿是指某个热点key在过期的一瞬间大量请求同时打到数据库。比如大促时一个爆款商品的库存数据在Redis里过期了一瞬间所有用户请求都去查数据库。解决思路有两个方向一个是用互斥锁只让一个线程去重建缓存其他线程等待另一个是“逻辑过期”缓存里不设置TTL而是存一个过期时间字段后台异步刷新真实数据。后者的好处是用户请求永远不直接打DB但缺点是实现复杂度高。雪崩则是大量key在同一时间段集中过期或者Redis实例整体不可用导致所有请求落到数据库上数据库瞬间被打垮。应对方案包括设置过期时间时加一个随机抖动比如基础TTL加0到300秒的随机值错开过期时间做多级缓存把热点数据兜在本地缓存里减少对Redis的直接依赖接口层做限流和熔断防止数据库被彻底打挂。我面过不少候选人能把三个概念分清楚的大概有六成能结合自己的业务场景说明选择理由的可能不到两成。所以在这道题上我强烈建议你准备一个自己项目里的真实案例哪怕很小也比你背十个解决方案更有说服力。4. 避坑经验40道题背完还会挂的几个原因4.1 只背结论不会推演追问一层就露馅我把面试里常见的翻车现场整理了一下大家可以对照自查。问题现场根本原因正确准备姿势volatile能背出可见性和有序性但说不出底层怎么保证只记结论没有理解JMM和内存屏障去查一下内存屏障和lock前缀的含义能画出CPU缓存与主存交互图知道Bean生命周期各个方法名但说不清循环依赖为什么用三级缓存知识点碎片化没有串联源码流程按“实例化、属性填充、初始化”的主线理解Bean创建过程Redis三兄弟分得清但项目一问就沉默没有把八股知识和现场经验绑定每个典型方案准备一个“我在哪个系统里用过/如果让我设计我会怎么做”的小故事被问“没做过这个功能怎么办”时直接说不会缺乏知识迁移能力先说思路再类比已经掌握的技术给出可落地的方案这些问题的共性就是“背诵”和“理解”之间缺了一道桥。背题只能让你答出第一层桥需要靠推演和提问自己搭起来。4.2 答题节奏不对一上来就倒豆子考官反而没法追问有一种候选人答八股题像背课文。面试官刚问完synchronized他从原理到锁升级到偏向锁撤销到锁粗化全部一口气倒出来中间不带停。这其实是减分行为。因为面试官心里有一套既定的追问路径他需要在你回答的时候找到切入点来判断你的理解深度。你一倒豆子他只能等你背完再挑一个点继续问整个过程很累。比较好的做法是“结论先行分层展开”。先给出核心结论停顿一下观察面试官是否示意你继续再往下展开。比如问synchronized你先说“synchronized在JDK6之后引入了锁升级机制本质是通过对象头里的Mark Word来记录锁状态”然后停一下。面试官如果对这个点感兴趣会继续追问“锁升级的条件是什么”你再展开。这样既不会让面试官觉得你只会背又给了对方追问空间整个对话会自然很多。4.3 基础题答完不落地丢失了展示项目经验的机会八股题答得再完美也只是半个答案。另外半个在于你怎么把它连接到项目经历上。面试官问线程池参数你答完流程后顺手说一句“我们网关服务里就遇到过队列堆积的问题当时把无界队列改成了有界队列并加了线程池监控”这就是一个很自然的项目加分点。它不需要你特意把话题扯到项目上但需要你提前在每题旁边标注“这个知识点对应我项目里的哪个场景”。我建议你复习时准备一个文档40道题每道题下面写两行场景备注面试前反复看两遍效果立竿见影。5. 两周冲刺计划与自测方法5.1 第一周按模块扫盲建立知识点之间的联系准备面试最忌讳每天东看一眼西看一眼。建议按模块推进Day1到Day2集中过Java基础与集合HashMap一定要画图Day3到Day4主攻JVM和并发这两块可以放在一起理解因为都涉及内存模型Day5主攻MySQL索引与事务多练SQL判断Day6主攻Spring生命周期和循环依赖Day7集中刷Redis和网络高频题。5.2 第二周从“会背”到“会讲”做输出训练第二周不要再看新题而是做输出训练。每天都从40道清单里随机抽10道题打开手机录音每道题用三到五分钟口述回答。录完必须回放重点听三件事有没有卡壳超过五秒的地方专业术语是否用得准确是不是每道题都只答了定义而没展开。这个方法虽然有点费时间但它是我见过效率最高的查漏补缺方式。5.3 用“费曼式自测”检验自己是不是真理解了检验自己是否理解一个知识点的最好方法就是能不能用大白话给别人讲明白。你可以在复习完一个模块后假装对面坐着一个刚入行的同事把“synchronized锁升级”“MVCC可见性”“Spring三级缓存”这些概念用生活化的比喻解释一遍。比如锁升级就可以类比成“自习室抢座位一开始没人抢就只用标记一下抢的人多了开始加锁锁竞争激烈了就升级成管理员挨个检查”。能讲出这样的类比说明你确实理解了这个机制如果你只能照着原话念那就说明还需要回到原理去补课。最后再分享一个我面试别人时很喜欢的瞬间候选人答完基础题后坦诚地说“这个底层细节我不太确定但根据我对JMM的理解它应该是这样工作的”。这种回答几乎不会扣分反而会让面试官看到你的逻辑推导能力和诚实度。八股文准备到最后真正值钱的是你脑子里那张互相连接的知识网。你可以卡在一两个细节上但只要大框架不乱你就已经赢过大多数人了。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →