一份Java面试复习清单:覆盖集合、JVM与Spring
2026/9/2 3:19:53 网站建设 项目流程

集合、JVM与Spring,这三个词几乎就是Java面试的“三座大山”。你背过的那些八股文,在真正的追问下不堪一击,因为面试官要的不是答案,而是你脑子里有没有那棵知识树。这份清单不是让你死记硬背,而是帮你把碎片化知识重新焊接成一套能“扛住深挖”的思维框架。如果你只有三天时间,请把所有精力放在这三件事上:集合底层是数据结构与并发的镜子,JVM是Java与操作系统之间的契约,Spring则是你理解“工程化设计”的试金石。

集合:别再背源码,去画数据结构图

ArrayList和LinkedList的区别,几乎每个面试者都能背出“数组 vs 链表”。但当你被问到“ArrayList在频繁删除元素时性能为何急剧下降,而LinkedList就一定能赢吗?”很多人会卡壳。真正的答案藏在“内存布局”和“局部性原理”里——数组在内存中连续,CPU缓存友好,而链表节点分散,每次访问都可能触发缓存缺失。你画一张内存示意图,比背十遍源码有效。面试官让你说HashMap原理,如果你只是复述“数组+链表+红黑树”,那么你只值五分。要说的是一棵红黑树插入时如何旋转、为什么树化阈值为8、为什么退化阈值是6,以及负载因子0.75背后的“空间与时间的权衡”。甚至可以追问:为什么用红黑树而不是AVL树?因为红黑树牺牲严格平衡换取更少的旋转次数,在写入频繁的场景更实用。这才是“有深度的理解”,不是“背诵”。

ConcurrentHashMap是并发题的分水岭。旧版用分段锁,新版用CAS + synchronized。面试官问“为什么JDK8还要用synchronized而不是完全CAS?”答案很讽刺:在高竞争场景下,CAS自旋会造成严重的CPU浪费,而synchronized在锁升级为重量级锁后会阻塞线程,反而节省了CPU。更关键的是,你要能画出“put”操作的全过程:先算hash,然后判断table是否初始化,接着用CAS插入空桶,如果桶不为空则锁住头节点,再遍历链表或红黑树。很多人只记住“CAS + synchronized”,却忘了“协助扩容”和“ForwardingNode”这类细节。面试官只要轻描淡写地问一句“扩容时其他线程能继续put吗?”就能卡掉八成候选人。你至少要知道:读操作可以并发,写操作如果遇到ForwardingNode会帮助迁移或等待。记住,并发集合的核心是“让锁的粒度尽可能小,甚至无锁”。

JVM:内存模型与调优,是“操作系统课”的续集

JVM面试题,从“运行时数据区”到“垃圾回收器”,几乎人人会背。但面试官最恨的就是“背完五块区域名字就停”的人。你讲堆、栈、方法区时,能不能顺带说一句“栈是线程私有,所以栈上的局部变量天然线程安全;堆是线程共享,所以需要同步机制”?用这种“对比+原因”的方式,一秒拉开差距。紧接着是内存溢出问题:栈溢出(StackOverflowError)通常因为递归调用太深,而堆溢出(OutOfMemoryError)则是因为对象无法被回收或分配超大数组。如果你能现场画一个“对象出生在Eden区,经历Minor GC后进入Survivor,年龄到15后晋升老年代”的生命周期图,并且解释为什么是15而不是7,那么JVM基础分就拿稳了。

垃圾回收是深水区。 G1回收器最核心的设计是“把堆分成多个Region,用记忆集(Remembered Set)追踪跨Region引用,从而避免全堆扫描。” 面试官如果问“CMS和G1有什么区别”,你不能只说“CMS标记清除、G1标记整理”,而要提到停顿预测模型——G1会预测每个Region回收后的停顿时间,然后优先回收那些“回收收益最大”的Region。这种“可控停顿”的思想,恰恰是Java服务端追求SLA的必备技能。更进一步,你会不会被问到“什么是三色标记法?为什么会产生漏标?怎么解决?”如果你能扯出“增量更新”和“原始快照(SATB)”的区别——CMS用增量更新,G1用SATB——那就说明你真的读进去了。别恐慌,“并发标记”阶段很可能出错,但理解它比记住每个参数更有价值。

调优层面的问题,往往是“你遇到过线上内存溢出吗?怎么排查?”这时候最怕一句话回答“用jmap看了下堆”。你要给出完整路径:先用jps定位进程,再用jstat -gcutil看GC频率,接着jmap -dump:format=b导出堆快照,然后用MAT或VisualVM分析大对象或Dominator Tree。如果你能顺便提一句“我习惯在启动参数里加上-XX:+HeapDumpOnOutOfMemoryError”,面试官眼睛会亮一下。另一个角落是“类加载机制”。双亲委派模型的精髓不是“向上委派”,而是“避免核心类被篡改”。但当面试官问“怎么打破双亲委派?”你必须答出Tomcat的WebAppClassLoader——每个WebApp有独立类加载器,为了隔离不同应用的类库版本,以及JSP热更新时“丢弃旧的类加载器重新创建”。如果你能把“双亲委派”和“类加载隔离”这两个概念对立统一起来,就证明你理解了框架设计者的苦衷。

Spring:核心不是AOP与IOC,而是“依赖管理的哲学”

Spring面试题永远是“什么是IOC?什么是AOP?”但说实话,这两个概念背出来并不能让你突出。你要回答的是:IOC容器本质上是一个“对象工厂+依赖登记表”,它改变了对象的创建时机和生命周期管理方式——对象不再由自己new,而是由容器组装。更深一层:DI(依赖注入)和IOC是同一件事吗?严格来说,IOC是思想,DI是它的实现方式之一。面试官想听到的是你有“概念辨析”能力。但光有思想还不够,你必须能说清Bean的生命周期:实例化、属性填充、BeanNameAware回调、BeanPostProcessor的前置处理、InitializingBean和init-method、BeanPostProcessor的后置处理、使用、销毁。如果只记得“构造、初始化、销毁”,那你连及格都难。 Spring容器最骚的操作其实就是BeanPostProcessor,它能让你在Bean初始化前后“劫持”一番,Spring的各种注解驱动、代理生成,全部藏在这里。

AOP部分,经常有人把“切面、切点、通知”背得滚瓜烂熟。但一问“Spring AOP是运行时代理还是编译时织入?”就糊涂了。默认是运行时代理:接口用JDK动态代理,类用CGLIB子类代理。你还可以进一步说明“为什么JDK代理必须基于接口?”因为Proxy.newProxyInstance会生成一个实现接口的代理类,它只能通过接口暴露方法。然后追问“哪种代理性能更高?”其实高版本JKD动态代理在经过优化后,性能已经接近CGLIB,但CGLIB在创建代理时开销较大。更高级的面试问题还包括“事务管理失效的场景有哪些?”无论你多熟练,都可能漏掉“方法内部调用(this.xxx())导致代理失效,因为这是绕过代理直接调用目标方法”。如果你能顺带说出“解决方案是注入自身代理或使用AopContext.currentProxy()”,再补一句“@Transactional默认只回滚RuntimeException,检查异常不会回滚”,这个环节基本稳了。

Spring还有一大主题是“循环依赖”。很多面试者知道“三级缓存”,但说不清为什么需要三级,而不是两级。第一级缓存存成品Bean,第二级存早期暴露的Bean(尚未填充属性),第三级存ObjectFactory(用于产生代理对象)。核心逻辑是:当A依赖于B、B依赖于A时,先让A暴露一个早期引用(放入三级缓存),B创建时可以直接引用这个早期A,从而打破死锁。但如果不需要代理,为什么还要第三级?因为Spring希望“提前暴露的是最终代理对象”,而代理对象只有在实例化后才知道是否需要创建(通过切面判断)。如果没有三级缓存,只靠二级缓存,那么单例模式下循环依赖虽然可以解决,但AOP代理的时机就会错乱,可能导致B拿到的是未代理的A。这么一解释,你就回答了“为什么要三级缓存”的真正原因——不是为了解决循环依赖,而是为了在解决循环依赖的同时还保持AOP代理的正确性。这句话记下来,面试中直接降维打击。

SpringBoot呢?核心不是“自动配置”这个结果,而是EnableAutoConfiguration、@ConditionalOnMissingBean、spring.factories(或META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports)这套“条件装配机制”。如果你能展开说“SpringBoot为什么能基于pom依赖就能装配WebMVC?因为AutoConfiguration类被加载后,会根据当前classpath是否包含DispatcherServlet和Servlet容器来决定是否创建相关Bean”,那你就不只是一个“会用SpringBoot的人”。另外,Spring中的设计模式也是爱考的高频点:BeanFactory是工厂模式,AOP代理是代理模式,事件监听是观察者模式,JdbcTemplate是模板方法模式,Spring的Resource是策略模式。不要背“一种模式对应一个类”,而是回答“这种模式在Spring中解决了什么问题”。

把这个清单变成你的“肌肉记忆”

以上知识,你不是看了就等于会了。你必须用“自问自答”的方式做输出训练:拿到任何一道题,先自己说上三分钟,然后回放,看哪里卡壳。集合的底层数据结构、JVM的内存分区与GC流程、Spring的Bean生命周期与循环依赖,这三条主线相互独立又能交叉联动。比如“HashMap在多线程下丢失数据,和JVM重排序有什么关系?”或者“Spring的默认单例Bean在Spring容器里就是依赖JVM堆上的对象存储,那ThreadLocal里的Spring事务信息呢?”这些问题可以逼着自己把知识网织起来。面试不是考试背诵,而是“实战模拟”。只要你多问自己几次“为什么这样设计”“如果不这样设计会怎样”,再常见的八股,也能变成你独到的见解。这份清单或许不能保证你拿到Offer,但一定能让你在回答时“眼里有光”,而不是“嘴里有词”。

最后留一句扎心的总结:面试官真正在听的,不是你对某个知识点的“陈述”,而是你在被连续追问“为什么”之后,是否还能保持思路清晰。所以,请把这份清单当成你的“教练”,而不是“小抄”。每天抽出40分钟,一个子话题一个子话题地“讲给自己听”。一个月后,当你再听到“Java面试复习清单”这几个字,你会笑出来:因为那些知识已经不在清单里,而在你的血液中。这份清单,最后的目标是让你忘掉清单。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询