ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Java面试中高频核心知识点梳理与避坑指南

Java面试中高频核心知识点梳理与避坑指南 面试场上真正拉开差距的往往不是那些“背得滚瓜烂熟的定义”而是你能否在追问中把原理讲透、把坑点说破。很多候选人简历写得花团锦簇一到深挖细节就露怯。这篇文章不打算按教科书顺序平铺直叙而是直接切入选人单位最常戳的痛点把高频考点和那些让你“事后拍大腿”的陷阱一次性捋清楚。集合框架别只背八股要懂“为什么”面试官问“HashMap底层结构”时百分之八十的人能答出“数组链表红黑树”。但紧接着追问一句“为什么阈值是8而不是9或10”时沉默的就占了一大半。答案其实藏在泊松分布里在负载因子0.75、哈希函数随机性良好的前提下链表长度达到8的概率已经低于千万分之一。设置8是为了让链表几乎不可能真正触发树化而一旦触发说明哈希冲突已经严重异常此时用树结构换取极端情况下的查询性能。这个细节不是让你背数字而是检验你是否理解“概率模型”与“工程权衡”。避坑点在于“扩容”时的死循环问题。JDK7的resize采用头插法多线程并发扩容会形成环形链表JDK8改为尾插法解决了这个问题但并不代表HashMap线程安全。并发场景下HashMap丢数据、size不准、甚至CPU飙到100%都毫不稀奇。面试官经常设的陷阱是既然JDK8修了死循环那HashMap可以在多线程用了吗正确答案是死循环修了但竞态条件没修你依然需要ConcurrentHashMap。再谈ConcurrentHashMap的锁机制。很多人知道JDK8放弃了分段锁改用CASsynchronized。但为什么要换分段锁的Segment本质是数组里的一个ReentrantLock锁的粒度是“一段”而JDK8的synchronized锁的是链表或红黑树的头节点粒度更细。更深层的原因是synchronized经过JVM持续优化偏向锁、轻量级锁后在竞争不激烈的场景下性能已不输ReentrantLock而且代码更简洁。面试时主动提“锁升级”路径会让面试官觉得你不是背源码而是真看懂了。JVM内存模型与GC是照妖镜“JVM运行时数据区”是必考题但很多人画完堆、栈、方法区后就停了。这里有个高频陷阱方法区在JDK8里被移到了元空间元空间使用本地内存而不是JVM堆内存。如果你还在说“永久代”面试官基本能断定你停留在JDK7。至于为什么移因为永久代大小难以预测时常抛出OOM而本地内存只受物理内存限制可以更灵活地容纳动态生成的类元数据。GC算法方面几乎所有面试官都会问“如何判断对象已死”。引用计数法因为解决不了循环引用问题已经成了历史所以默认答案是可达性分析。但厉害一点的候选人会补充“即使在可达性分析后对象也有机会自救——在finalize()中被重新引用。”不过紧接着要强调finalize()调用时机不确定、性能差现代代码早就该无视它了。这才是避坑重点你可以提它但不能推荐它。关于垃圾收集器G1已经成了JDK9后的默认但面试官更爱问“G1和CMS有什么本质区别”。CMS基于标记-清除会产生碎片且并发标记阶段会与用户线程争抢CPUG1基于Region局部回收能预测停顿时间。但更深的考点在于“G1的Remembered Set”和“卡表”——很多人死在“什么是跨代引用”上。记住这个解释G1每个Region都会记录“其他Region指向本Region的引用”叫RSet。修改对象引用时通过写屏障维护RSet。这个机制决定了G1的并发标记能精准找到根对象避免全堆扫描。避坑指南被问“G1什么时候会退化为Full GC”时很多答案是“巨型对象分配失败”或“回收速度跟不上分配速度”。但真正的底层原因是由于并发收集时RSet更新不及时导致需要暂停用户线程进行“串行Full GC”。这个细节能帮你从“背参数”跳到“懂原理”。并发编程从synchronized到AQS层层剥开如果候选人只能说出“synchronized是重量级锁”那基本没戏。现在的考点是锁升级无锁→偏向锁→轻量级锁→重量级锁且偏向锁在JDK15已被标记过期JDK17默认关闭。回答时要带上触发条件偏向锁是同一个线程反复进入轻量级锁是少量线程竞争自旋等待重量级锁是竞争激烈操作系统互斥量接管。面试官最忌讳的是“在无竞争时锁会有额外开销”这种错误观点——偏向锁和轻量级锁恰恰是为了消除这种开销。AQS是全职Java岗位的“魔鬼关卡”。核心三要素volatile state变量、CLH队列变体、LockSupport.park/unpark。但面试官往往不会问你“state是什么”而是问“ReentrantLock的可重入是怎么实现的”。答案thread是当前持有线程加锁时判断持有线程是否为当前线程是则state1。释放时每unlock一次state-1直到为0才真正释放锁。这还不算完还要能回答“公平锁和非公平锁的差异”——非公平锁在加锁前会直接CAS抢一次state抢不到才进队列公平锁必须检查队列里有没有前驱节点。避坑点很多人以为非公平锁一定不公平其实它只是“插队”并不会饿死队尾线程因为CAS失败就会乖乖排队。ThreadLocal也是个深水区。每个线程持有自己的ThreadLocalMapkey是ThreadLocal的弱引用value是强引用。一旦Key被回收value就成了“内存泄漏点”。解决方案是每次用完调用remove()。面试时你还要能解释为什么key用弱引用——是为了防止ThreadLocal对象永不回收。但value用强引用导致“key为null的entry”无法被访问必须靠remove或get时的清理逻辑打扫。这个“弱引用陷阱”是高频考点答对的人极少。SpringIOC和AOP的底层逻辑别只会注解Spring几乎是所有Java面试的压轴题。老套路问“Bean的生命周期”但新套路问“循环依赖怎么解决”。核心答案是三级缓存一级缓存存成品Bean二级缓存存早期曝光对象半成品三级缓存存ObjectFactory用于解决AOP代理。如果A类依赖BB依赖A创建A时会提前把A的ObjectFactory放入三级缓存等B创建时需要A时通过工厂拿到早期引用。关键点只有单例且允许循环引用才支持prototype不支持构造器注入不支持。很多人背了“三级缓存”却说不清为什么需要三级而不是二级——答案是如果不做AOP二级就够了但需要AOP时三级缓存能在不提前暴露代理对象的情况下保留“最终生成代理”的灵活性。AOP面试陷阱在于动态代理的选择。JDK动态代理只能代理接口CGLIB可以代理类。Spring默认行为目标类实现了接口用JDK代理没实现接口用CGLIB。但SpringBoot2.x之后spring.aop.proxy-target-class默认true强制用CGLIB。所以别再回答“默认JDK动态代理”了那是老黄历。避坑点CGLIB通过继承生成子类所以目标类的方法不能被final修饰否则无法增强。事务失效是实战派面试官的最爱。“为什么自调用会导致事务失效”因为Spring事务基于代理自调用时this调用方法没有走代理对象自然没有拦截器生效。解决办法注入自身代理Lazy)或者分开两个类或者用AopContext.currentProxy()。另外一个高频坑方法被private修饰、异常被try-catch吞掉、数据库引擎MyISAM不支持事务——这三条是事务失效的“三座大山”。面试时能把“自调用”放在第一位说明你真的写过业务。MySQL索引与锁实战中的送命题索引这块最容易被问倒的是“联合索引的最左前缀原则”和“索引下推”。很多人知道最左前缀但不知道“跳过的中间列会如何”。比如联合索引(a,b,c)查询条件where a1 and c2此时只有a能用到索引c无法使用——因为b缺失导致c无法定位优化。但加上索引下推后存储引擎会把a1的索引记录先取出来再用c2在存储引擎层过滤减少回表次数。这就是“索引下推”的价值。这个细节已经从“加分项”变成了“基础项”。锁的陷阱更加隐蔽。InnoDB的锁是加在索引上的如果查询没走索引行锁会升级成表锁。这就是为什么你在update where条件没命中索引时明明改一条却锁住全表并发直接炸穿。另一个坑是间隙锁Gap Lock——在可重复读级别下范围查询会锁住“记录和记录之间的间隙”防止幻读。所以你以为在update一个范围内不存在的数据结果把整个区间都锁了。面试官经常问“为什么MySQL默认隔离级别是可重复读而不是读已提交”除了历史原因更实际的解释是在binlog是statement格式时读已提交会导致主从数据不一致可重复读配合间隙锁能杜绝这个问题。这又是一个“懂原理”的分水岭。Redis缓存穿透、击穿、雪崩的防御体系三大经典问题的区别穿透是“查询一个不存在的数据”击穿是“热点key过期瞬间大量请求打到DB”雪崩是“大量key同时过期”。但避坑指南在于解决方案的误区。穿透不能用“缓存空值”一劳永逸因为恶意攻击会用不同不存在的key刷爆缓存——需要布隆过滤器前置拦截。击穿可以用互斥锁或逻辑过期value里存过期时间但逻辑过期方案会返回脏数据业务要能容忍。雪崩不要只想着随机过期时间更稳健的是做好Redis集群高可用多级缓存本地缓存兜底。另一个高频考点是Redis持久化。RDB是定期快照AOF是追加日志。回答“选择哪种”时不能只说“AOF可靠”还要说“RDB恢复快、文件小”。真正的陷阱在AOF重写机制——重写不是基于当前内存数据重新生成命令而是基于“当前数据库状态”生成最小命令集。如果你答不出“子进程重写写时复制”来避免阻塞主线程那基本扣一半分。避坑总则别让“背过的术语”成为你的掘墓人面试官最擅长“顺着一个点往下挖”。你提到“G1”他会问“RSet怎么维护”你提到“ThreadLocal”他会问“为什么内存泄漏”你提到“Spring事务”他会问“自调用怎么解决”。所以准备工作不是背答案而是对每个核心概念都准备“原理场景坑点”的三层结构。切忌只停留在“用过哪些技术”的列表层面。用一句话总结高频考点考的是你的“熟练度”避坑指南考的是你的“辨别力”。而真正决定Offer的往往就是当你自信地抛出“因为我们用的默认隔离级别是可重复读”之后你还补得上“间隙锁”这三个字的那一刻。
返回列表