2026年Java面试26个核心考点:从原理到实战的完整追问指南
最近后台收到一堆同学的面试复盘印象最深的一条是面某中厂后端三轮面试没有一轮直接问“HashMap原理背一遍”而是从“线上偶发死锁怎么排查”聊起顺藤摸瓜把线程状态、锁升级、字节码甚至操作系统调度全串了一遍。这就是2026年Java面试的常态——考点还是那26个核心考点但问法已经从“填空题”变成了“案件重演”。这篇文章把2026年3月前后最常出现的Java面试核心考点做了系统整理每个考点都配了代码示例或排查路径适合正在准备中级、高级Java岗位面试的同学也适合想系统自查技术体系的在职开发。文章不按教科书目录排而是按面试官实际追问的逻辑排——你先看到的是“为什么会这么问”然后才是“该怎么答”。1. 2026年Java面试风向八股文不再是唯一标尺1.1 面试形式变了从背答案到造场景过去大家理解的面试题是“ConcurrentHashMap说一下原理”“线程池参数有哪些”标准答案背熟就能过。现在的主流问法是给一个场景让你自己发现问题、拆解问题、给出方案。比如某同学复盘时提到面试官问的不是“Redis为什么快”而是“你们缓存命中率突然从95%掉到70%你怎么定位”。这道题表面上考缓存实际把过期策略、键设计、大Key、热Key、持久化阻塞、网络IO全扯进来了。你需要现场画一条排查链路而不是背一段结论。所以2026年的备考方式必须从“记答案”改成“建模型”。每个考点背后都要明白至少两层第一层是什么定义和原理第二层是为什么设计动机和适用边界。能答出第二层面试官才会认为你有实战判断力而不仅仅是个移动题库。1.2 26个考点的分布逻辑与复习优先级我按面试中出现频率和追问深度把这26个考点分成五个大模块JVM与性能、并发编程、集合与语言特性、数据库与缓存、Spring与微服务。这个分布不是随意凑的它对应的是后端岗位日常工作中最常出问题的五个区域JVM和并发线上故障排查的重灾区OOM、死锁、CPU飙高都在这两个模块里。集合和语言特性源码级基础面试官用来快速判断代码功底。数据库和缓存绝大多数业务系统的性能瓶颈所在也是场景题最爱出题的地方。Spring与微服务项目经验的必答区尤其事务和分布式一致性。复习优先级上我建议把并发和数据库缓存放在最前面因为这两个模块能同时覆盖“原理题”和“场景题”。集合和JVM可以穿插着看语言特性比如Record、Sealed Class属于性价比极高的考点背一下就能拿分但很多人容易忽略。2. JVM与并发高频题里的“体力活”与“硬技术”2.1 JVM内存模型与“对象一定在堆上吗”的反直觉答案JVM内存分区是送分题但2026年的面试官不会满足于“堆、栈、方法区”六个字。真正的分水岭问题有两个对象一定分配在堆上吗什么时候会在栈上分配答案是否定的。当对象未发生逃逸时JVM通过逃逸分析确认它不会被外部方法访问可能将对象拆散并分配到栈上或寄存器中这就是栈上分配。典型场景是循环内部创建的局部对象比如public long sum(long[] arr) { long total 0; for (long v : arr) { Point p new Point(v, v); // 未逃逸可能栈上分配 total p.x p.y; } return total; }这段代码里的Point对象每次循环都会创建如果都进堆GC压力会非常大。逃逸分析开启后默认开启它可能被分配到栈上方法结束即销毁完全不用GC介入。搭配记忆的点还有两个TLAB线程本地分配缓冲解决的是“多个线程在堆上并发分配时的竞争问题”每个线程在Eden区划一块私有空间指针压缩则是在堆内存小于32GB时通过压缩普通对象指针来减少内存占用。这三件事连起来才算把“对象分配”这个环节讲透。2.2 垃圾回收器选型G1 和 ZGC 的取舍别只看暂停时间G1已经是老生常谈但2026年还在大量线上系统服役。它的核心思路是把堆分成若干大小不一的Region通过维护一个优先级列表优先回收价值最大的Region目标是在可控暂停时间内完成尽可能多的回收。ZGC的特点是几乎不暂停应用线程依靠染色指针和读屏障实现并发标记、并发转移。它的停顿时间基本稳定在1毫秒以内而且不随堆大小增长。但ZGC不是银弹它更吃内存和CPU适合大堆、低延迟场景。我整理了一份选型对比面试时可以直接用对比维度G1ZGC设计目标可预测的暂停时间默认200ms极低停顿亚毫秒级实现基础Region分代回收染色指针、读屏障、并发转移适用堆大小中等大堆几GB到几十GB超大堆几十GB到数百GB主要代价需调优Region和暂停目标额外内存开销与CPU占用常见参数-XX:MaxGCPauseMillis200-XX:UseZGC追问环节常问“线上什么时候该换ZGC”。我的建议答案是当业务对延迟极其敏感、堆内存已经无法通过优化代码降低、G1的暂停时间已经影响可用性时才考虑换。换之前先做压测对比观察最坏停顿而不是平均停顿。2.3 锁的升级过程与 ReentrantLock 的底层逻辑synchronized和ReentrantLock的区别是经典题但高分回答要能讲出锁升级的完整链路无锁 → 偏向锁 → 轻量级锁 → 重量级锁。偏向锁假设同一线程反复获取锁用一次CAS记录线程ID一旦有竞争升级为轻量级锁通过自旋在用户态争取自旋超过阈值或竞争激烈才升级为重量级锁进入操作系统互斥量线程真正阻塞。这里有个容易答错的坑偏向锁在JDK 15中默认被禁用JDK 17之后已经彻底移除。很多八股文还在讲偏向锁是默认开启的2026年面试这么说会露馅。新版本里锁启动直接进入轻量级锁阶段自旋选项也不再需要手动配置。ReentrantLock相对synchronized的优势核心是可中断、可超时、可多条件绑定。写一个标准模板Lock lock new ReentrantLock(); Condition notEmpty lock.newCondition(); // 加锁 lock.lock(); try { // 临界区代码 // condition.await() / signal() } finally { lock.unlock(); }实际开发中最容易犯的错是try块里加锁、finally块里忘记解锁或者把lock()放进try里导致加锁失败也走finally解锁结果抛出IllegalMonitorStateException。模板的正确写法是lock()必须在try之前unlock()必须放在finally第一行。2.4 线程池参数设计永远不要只用默认值线程池参数面试问得极多但很多人只背参数名答不上来具体怎么定。ThreadPoolExecutor七个参数里最核心的是核心线程数、最大线程数、阻塞队列和拒绝策略。核心线程数不是算出来的而是根据任务类型区分的。CPU密集型任务核心线程数≈CPU核数1IO密集型任务核心线程数可以放宽到CPU核数×2甚至更多因为大部分时间线程在等待IO不占用CPU。更合理的做法是结合压测结果调整而不是套公式。拒绝策略的选择也很有讲究。AbortPolicy直接抛异常适合不允许丢弃任务的场景CallerRunsPolicy让提交者线程自己执行任务适合需要降速保底、又不希望任务丢失的场景DiscardOldestPolicy丢弃最旧任务适合实时性要求高的缓存场景。ThreadPoolExecutor executor new ThreadPoolExecutor( 8, // 核心线程数 16, // 最大线程数 60, TimeUnit.SECONDS, // 空闲线程存活时间 new ArrayBlockingQueue(100), // 有界队列 new ThreadFactoryBuilder().setNameFormat(business-pool-%d).build(), new ThreadPoolExecutor.CallerRunsPolicy() );还有个高频细节队列用有界还是无界。无界队列会让最大线程数参数失去意义任务无限堆积最终内存溢出有界队列配合拒绝策略才能让线程池在流量洪峰时表现为“排队限流”而不是“吞掉所有任务直到崩溃”。2.5 虚拟线程与结构化并发Java 21后的必问题虚拟线程是2026年面试绕不开的新考点。它的核心价值是让Java以极低成本创建海量线程适合IO密集型任务。虚拟线程由JVM调度挂载在少数平台线程上执行遇到IO阻塞时自动卸载让出载体线程等待IO完成后重新挂载。写一个虚拟线程请求外部服务的典型示例// 每个请求一个虚拟线程成本极低 try (var executor Executors.newVirtualThreadPerTaskExecutor()) { FutureResult r1 executor.submit(() - callServiceA()); FutureResult r2 executor.submit(() - callServiceB()); FutureResult r3 executor.submit(() - callServiceC()); Result result new Result( r1.get(), r2.get(), r3.get() ); } // try-with-resources 自动等待所有任务完成并关闭结构化并发StructuredTaskScope则是把并发任务的创建、执行、取消纳入同一个代码块作用域任务要么全部成功要么统一失败处理避免线程泄漏和孤立任务。这是Java 21之后的并发编程新范式面试官如果问“虚拟线程会不会让线程池失效”可以回答线程池依然适用于CPU密集型和需要限流的场景虚拟线程真正改变的是IO密集型任务的资源模型。3. 集合与语言特性从源码看面试官的追问轨迹3.1 HashMap 的扩容、红黑树与容量陷阱HashMap考点密集最容易丢分的是三个细节。第一个是容量始终是2的幂目的是让hash散列后的下标计算用位运算(n - 1) hash替代取模速度更快。第二个是链表转红黑树的阈值是8但触发条件有两个链表长度达到8且数组长度不小于64。如果数组长度没到64会优先扩容而不是树化。第三个是红黑树退化回链表的阈值是6预留了1的差值避免频繁转换。还有一个容易被追问的并发问题JDK 7的HashMap在多线程扩容时会形成环形链表导致死循环JDK 8改成尾插法解决了死循环但并发put仍然会丢数据。所以面试题标准答案是“HashMap线程不安全并发场景用ConcurrentHashMap”但你要能解释为什么换了尾插法还是不安全因为两个线程同时扩容时彼此的引用拷贝依然可能覆盖。代码层面可以准备一个手写hash函数的变体static int hash(Object key) { int h; // 高16位与低16位异或让高位参与下标计算降低碰撞概率 return (key null) ? 0 : (h key.hashCode()) ^ (h 16); }追问“为什么是异或而不是直接取低位”时回答思路是如果两个hashCode低16位相同、高16位不同不扰动就会发生碰撞异或把高位信息混入低位让下标分布更均匀。3.2 ConcurrentHashMap 的锁粒度演进JDK 7的ConcurrentHashMap采用分段锁默认16个Segment每个Segment继承ReentrantLock锁粒度是Segment级别。JDK 8彻底抛弃分段锁改为CAS synchronized锁单个数组节点锁粒度细化到桶。初始化时不再预先分配Segment数组而是惰性创建Node数组。核心源码逻辑可以概括为三件事空桶通过CAS无锁插入非空桶通过synchronized锁住头节点扩容时多个线程协作迁移数据而不是单线程rehash。synchronized在JDK 8之后做了锁升级优化所以锁单个节点的成本远低于想象这也让ConcurrentHashMap在高并发读写下表现出色。面试官常追问的是size()方法。JDK 8里没有全局锁而是维护一个baseCount和CounterCell数组并发加元素时通过CAS分散计数最后累加。所以size()返回的是一个近似值在并发环境下并不保证绝对准确。3.3 fail-fast 与 fail-safe 的真实触发条件集合遍历时出现ConcurrentModificationException是fail-fast机制在起作用。它的实现方式是ArrayList、HashMap等集合内部维护一个modCount字段每次结构性修改add、remove、clear都会modCount。迭代器在创建时记录expectedModCount每次next()都会检查两者是否相等不相等就立刻抛异常。这里有个容易忽略的细节普通set操作不会增加modCount所以并发修改元素值不会触发异常只有结构性修改才会。CopyOnWriteArrayList是典型的fail-safe集合写操作拷贝新数组迭代器遍历的是原数组快照因此不会抛异常但遍历期间看不到新写入的数据而且每次写都是数组拷贝写频繁场景性能很差。面试回答这类问题时最好把两个机制放在同一维度对比fail-fast是“检测到并发修改就快速失败”fail-safe是“读旧快照保证遍历稳定”后者的代价是内存和写性能。3.4 Record、Sealed Class 与模式匹配的实用场景语言特性题属于性价比最高的考点因为代码简单、答案明确而且能直接体现你是否关注新版本。Record是不可变数据载体自动生成构造器、equals、hashCode、toString适合做DTO和VO。public record OrderCreatedEvent( Long orderId, Long userId, BigDecimal amount ) { // 压缩构造器在构造时校验参数 public OrderCreatedEvent { if (amount null || amount.compareTo(BigDecimal.ZERO) 0) { throw new IllegalArgumentException(amount must be positive); } } }Sealed Class解决的是继承范围失控的问题一个类允许哪些子类继承由程序员显式声明。public sealed interface PayResult permits SuccessResult, FailResult, RetryResult { } record SuccessResult(String trxId, BigDecimal paidAmount) implements PayResult {} record FailResult(String code, String reason) implements PayResult {} record RetryResult(int retryTimes) implements PayResult {}配合Java 17的switch模式匹配可以写出非常清晰的逻辑String describe(PayResult result) { return switch (result) { case SuccessResult s - 支付成功金额 s.paidAmount(); case FailResult f - 支付失败 f.reason(); case RetryResult r - 需要重试当前次数 r.retryTimes(); }; }追问陷阱通常是“Record和Lombok的Data有什么区别”。要点是Record是语言级不可变约束所有字段final且继承自java.lang.Record不能扩展父类Lombok本质是编译期注解处理器生成的类仍然是普通类。Record更适合值对象Lombok更适合需要灵活可变对象的场景。4. 数据库与缓存一条 SQL 能问出三轮“为什么”4.1 索引结构、最左前缀与回表索引题最核心的是理解B树为什么是默认结构。B树内部节点不存数据只存索引键因此单节点能容纳更多键树更矮IO次数更少叶子节点用双向链表串联范围查询只需顺序遍历叶子。聚簇索引的叶子节点存储整行数据二级索引的叶子节点存储主键值。所以通过二级索引查询但需要非索引列时要利用主键回表。覆盖索引则是索引本身包含所有需要查询的列不用回表。设计索引时的核心规则是最左前缀原则联合索引(a, b, c)能命中(a)、(a,b)、(a,b,c)但(b,c)不知道。因为B树先按a排序再按b排序最后按c排序跳过了a就无法利用索引的有序性。CREATE TABLE orders ( id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL, status TINYINT NOT NULL, create_time DATETIME NOT NULL, amount DECIMAL(12,2), KEY idx_user_status_time (user_id, status, create_time) ); -- 命中索引(user_id) -- 命中索引(user_id, status) -- 命中索引(user_id, status, create_time) -- 不命中最左前缀(status, create_time)最容易踩的坑是在索引列上做函数运算比如WHERE DATE(create_time) 2026-01-01这样索引列被函数包装B树无法按原键值二分定位索引失效。正确写法是范围条件WHERE create_time 2026-01-01 AND create_time 2026-01-02。4.2 事务隔离级别与 MVCC 的实现闭环隔离级别这个考点抽背定义只是基础高分答案要把“问题-级别-MVCC实现”一条线讲通。隔离级别解决的并发问题仍存在的问题读未提交无脏写、脏读、不可重复读、幻读读已提交脏读不可重复读、幻读可重复读脏读、不可重复读幻读串行化全部并发度极低MVCC多版本并发控制是读已提交和可重复读的实现基石。每行数据有隐藏列事务ID和回滚指针undo log维护版本链每个事务有一个ReadView记录活跃事务列表。可重复读和读已提交的区别核心在于ReadView的生成时机。读已提交是每次SELECT都生成新ReadView所以能看到别的事务新提交的数据可重复读是事务内第一次SELECT生成ReadView后固定复用后续SELECT永远只看到这个快照。这也是为什么可重复读下幻读不“完全”出现但如果是当前读SELECT ... FOR UPDATE还是可能通过间隙锁才保证不出现幻读。面试官如果追问“可重复读为什么能解决不可重复读”最直接的回答是它本质上不是“禁止别人修改”而是“修改后的新版本对当前事务不可见”这就是快照隔离的含义。4.3 慢 SQL 排查EXPLAIN 里的几个关键字段场景题“线上有一条SQL突然变慢”是2026年的高频考点。排查路径应该是先确认慢日志开关和阈值再拿到具体SQL然后EXPLAIN查看执行计划最后确定是索引失效还是扫描行数爆炸。EXPLAIN需要重点看的字段有四个字段关注点危险信号type访问类型出现ALL说明全表扫描至少要达到range或refkey实际使用索引NULL表示没走索引rows预估扫描行数远大于实际数据量说明统计信息或SQL写法有问题Extra额外信息Using filesort、Using temporary、Using index condition需注意典型案例如下EXPLAIN SELECT order_id, user_id, amount FROM orders WHERE user_id 10086 ORDER BY create_time;如果type是index且Extra是Using filesort说明优化器选了二级索引但不满足排序需要额外排序。解决思路通常是加索引(user_id, create_time)让索引顺序直接覆盖排序需求避免filesort。4.4 Redis 持久化与缓存一致性怎么答Redis持久化考的是RDB与AOF的取舍。RDB是内存快照恢复快、文件紧凑但两次快照之间的数据可能丢失AOF是操作日志追加丢数据少但文件体积大、重启恢复慢。生产环境常用混合持久化AOF重写后生成RDB快照作为基础再追加增量AOF日志兼顾恢复速度和数据安全。缓存一致性更常以场景题出现更新数据库后缓存怎么删、先删缓存还是先写库。目前实践中最稳妥的主流方案是Cache Aside读的时候先读缓存未命中则读库并回填写的时候先更新数据库再删除缓存。脏数据最容易出现在“先删缓存再写库”的流程里线程A删缓存线程B立刻读库并把旧值回填缓存随后线程A才更新数据库于是缓存永远停留在旧值。相比之下“先更新数据库再删缓存”并发窗口小很多配合延迟双删先删缓存→写库→休眠一小段→再删缓存能进一步兜底。面试时不要只背方案要说出权衡完全没有一致性问题是不可能的除非串行化实际系统能做的是把脏窗口压缩到极致再配合过期时间兜底让数据最终一致。4.5 分布式锁从 setnx 到 RedLock 的演进分布式锁是最典型的“从简单方案推到复杂方案”考点。最早的做法是用SETNX但必须带过期时间否则持锁进程宕机锁永远不释放。正确命令是SET lock_key unique_value NX EX 30这里unique_value必须唯一用于释放锁时校验“锁是我加的”防止误删别人加的锁。释放操作要保证原子性写成Lua脚本if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end单机Redis锁存在主从切换时锁丢失的风险于是有了RedLock的思想向多个独立节点依次加锁超过半数成功才算加锁成功。但RedLock本身也有争议很多人认为它复杂且不一定比单机加锁更安全。面试时可以说出这个权衡多数业务场景对绝对一致要求没那么高单机Redis锁配合看门狗续期已经够用如果真需要高可用分布式协同组件提供的临时顺序节点方案可能更可靠。5. Spring与微服务项目经验的“问薄了”现场5.1 Bean 生命周期与三级缓存循环依赖Spring Bean生命周期是一条完整的链实例化→属性填充→初始化前→初始化→初始化后AOP代理生成→使用→销毁。最常被追问的是循环依赖怎么解决。Spring解决循环依赖靠的是三级缓存// 第一级已完成完整生命周期的单例Bean MapString, Object singletonObjects; // 第二级提前暴露的早期Bean引用尚未完成属性填充和初始化 MapString, Object earlySingletonObjects; // 第三级ObjectFactory用于生成早期Bean引用的工厂 MapString, ObjectFactory? singletonFactories;流程大致是实例化A后A先把自己包装成ObjectFactory放入三级缓存再填充属性时发现需要B于是去创建BB填充属性时发现需要A此时从三级缓存拿到A的早期引用B完成创建A从B的创建过程中拿到B的引用并继续完成自己的属性填充和初始化。面试官常设的坑有两个。第一个是“构造器注入的循环依赖为什么解决不了”因为Bean实例化必须调用构造器A还没实例化完就无法放入三级缓存B拿不到A的引用。第二个是“三级缓存为什么是ObjectFactory而不是直接放对象”因为Spring可能在最后一步生成AOP代理如果早期直接放原始对象后面无法替换成代理对象用ObjectFactory可以延迟到真正需要引用时再决定暴露原始对象还是代理对象。5.2 事务传播行为五个默认值里藏着几个坑事务传播行为是Spring面试的高频细节题。传播行为定义了“当前方法的事务如何与已有事务交互”。最常用的是REQUIRED、REQUIRES_NEW、NESTED。传播行为行为描述典型使用场景REQUIRED有事务则加入无事务则新建默认值大多数业务方法REQUIRES_NEW挂起当前事务新开独立事务审计日志、异步通知失败不影响主流程NESTED嵌套事务基于保存点回滚批量处理中允许部分失败SUPPORTS有事务则加入无事务则不开启查询方法NOT_SUPPORTED挂起当前事务以非事务方式执行大数据量导出避免长事务实际开发最容易踩的坑是事务自调用失效同一个类里方法A调用方法BB上的Transactional不生效。因为代理机制只在外部调用时生效内部this.method()调用走的是原始对象不是代理对象。解决方式是拆分到不同Bean或者通过AopContext.currentProxy()。另一个高频坑是异常被吞导致事务不滚。Transactional默认只对RuntimeException和Error回滚检查异常不会回滚。如果业务方法捕获异常后不抛出事务必然正常提交数据就半途落库了。Transactional(rollbackFor Exception.class) public void createOrder(OrderDTO dto) { try { orderMapper.insert(dto); paymentService.deduct(dto.getUserId(), dto.getAmount()); } catch (Exception e) { // 这里重新抛RuntimeException事务才会回滚 throw new BizException(创建订单失败, e); } }5.3 分布式事务2PC、TCC、Saga 怎么选分布式事务是微服务架构的高阶考点。面试官通常不会让你把协议全程推演一遍而是给一个业务场景让你选方案并说理由。2PC两阶段提交是最直观的方案分为准备阶段和提交阶段协调者通知所有参与者准备全部成功后统一提交。问题在于协调者单点、同步阻塞、提交阶段失败难以恢复适合数据库资源较少、强一致要求高的内部系统。TCCTry-Confirm-Cancel把业务拆成三个阶段Try预留资源、Confirm确认执行、Cancel回滚。相比2PCTCC不依赖数据库XA性能更好但业务侵入性强每个操作都得实现三段逻辑。适合需要跨服务控制资源预留的场景比如下单预占库存。Saga适合长流程最终一致每个本地事务成功就发布事件失败则执行反向补偿。它没有全局锁并发性能好但隔离性弱中间状态对外可见。我整理过一张对比表面试直接用方案一致性业务侵入吞吐量适用场景2PC强一致低依赖资源管理器低数据库少、强一致TCC较强业务保证高三阶段编码中预占资源、跨服务写Saga最终一致中反向补偿高长流程、允许中间态5.4 幂等设计是分布式面试的保命题幂等这个考点几乎必问因为订单、支付、消息消费都会遇到重复请求。回答思路是给四层方案第一层唯一索引。数据库表加业务唯一键重复插入直接报错最原始也最可靠。第二层状态机。把订单状态流转做成有限状态机只有当前状态允许的目标状态才能执行对应操作天然拒绝重复推进。第三层token机制。前端提交前先获取token后端处理时删除token删除成功的请求才继续。第四层去重表。将请求唯一ID插入一张去重表插入失败说明重复后续直接返回上一次结果。这里要特别注意“消息消费幂等”的答法。不能只说“用Redis setnx”要讲清楚重复消费的根因是消费者处理超时后消息被重新投递解决思路是消费前先记录消息ID到去重存储消费完成后标记成功下次相同消息ID直接跳过。最好补一句“去重记录本身要有过期时间否则表会无限膨胀”。6. 临场实战26考点速查表与答题节奏6.1 26考点总表一句话答案与追问方向整理了一份速查表考前过一遍检查自己哪些考点能接住追问哪些只能说出名词。编号考点一句话核心答案常见追问方向1JVM内存分区堆、栈、方法区线程私有与共享对象一定在堆上吗2类加载机制双亲委派加载、验证、准备、解析、初始化怎么打破双亲委派3垃圾回收算法标记复制、标记清除、标记整理分代假设的依据4G1/ZGC选型根据堆大小与延迟要求选择换ZGC需要哪些前置条件5内存溢出排查先拿堆转储再用分析工具定位对象引用链什么情况会MetaSpace溢出6synchronized原理锁升级JDK15后移除偏向锁锁对象头里存了什么7ReentrantLock原理AQS队列同步器、ConditionAQS的state字段作用8volatile语义可见性、禁止指令重排为什么不能保证原子性9线程池参数核心、最大、队列、拒绝策略核心线程数怎么定10CompletableFuture异步编排、exceptionally、allOfthenApply和thenCompose区别11虚拟线程轻量线程、IO阻塞时卸载与线程池的适用边界12HashMap原理数组链表红黑树、扰动函数为什么树化阈值是813ConcurrentHashMapCASsynchronized锁桶size()是否准确14fail-fast机制modCount检测CopyOnWriteArrayList代价15字符串常量池编译期常量 vs 运行期intern两个字符串比较的编译优化16Record与不可变类语言级不可变载体与Lombok区别17Sealed Class显式限定继承范围与final类、接口默认方法的区别18索引与回表B树、最左前缀、覆盖索引索引失效场景19事务隔离级别四级隔离与并发问题映射可重复读如何实现20MVCCundo log版本链ReadView快照读与当前读的区别21EXPLAIN调优type、key、rows、Extrafilesort怎么消除22Redis持久化RDB快照AOF日志混合主从复制和持久化的关系23缓存一致性Cache Aside、延迟双删并发窗口如何产生24分布式锁SET NX EXLua释放主从切换锁丢失怎么办25Bean生命周期属性填充、初始化、AOP代理循环依赖为什么三级缓存26分布式事务2PC/TCC/Saga取舍幂等与分布式事务的关系6.2 现场答题节奏先说结论再讲过程面试答题最忌“从底层源码开始长篇大论”。正确的节奏是两步先给结论或直接答案再展开关键过程最后补一个边界或踩坑点。举个例子面试官问“HashMap线程安全吗”。先说结论“不安全并发场景应使用ConcurrentHashMap。”然后补关键原因“JDK 8之前的扩容头插法在并发下可能形成环形链表导致死循环JDK 8改成尾插法后不再死循环但并发put仍可能丢数据。”最后给个业务判断“所以单线程、查询为主的场景可以用HashMap并发写场景必须换工具。”整个回答控制在30秒内信息密度足够又给人“他真知道”的印象。6.3 复习误区只背不写、只看答案不反推这几年看到的备考失败案例几乎都栽在三个误区上。第一个是只看答案不反推“为什么”。比如背了“ConcurrentHashMap的size()不准”却不看CounterCell的设计动机也解释不了“为什么不直接加锁读取”一旦追问就露馅。第二个是只背参数不写代码。线程池七个参数背得滚瓜烂熟让手写一个带名字的ThreadFactory时直接卡壳。新特性题更是如此Record和Sealed Class如果只在资料上看过面试时连语法都写不对。第三个是忽略版本差异。2026年的八股文如果还在说“偏向锁默认开启”已经不符合标准JDK的新版本行为。备考时建议抓住JDK 17和21的LTS特性来看重点是虚拟线程、模式匹配、可空性相关改进。我自己的做法是最近跟进到了JDK 26手边开一个调试环境遇到新特性顺手跑一下语法印象比背书深得多。最后分享一个私藏经验考前别按资料目录刷按“追问树”刷。把每个考点当成一棵树根是定义枝是原理叶是踩坑案例。比如“Redis为什么快”的根是内存存储枝是单线程模型和IO多路复用叶是大Key阻塞、慢查询日志、持久化对性能的干扰。面到这个问题时你自然能沿着树往下走而不是背出“因为快”三个字就结束。2026年的面试真正拉开差距的不是谁背得多而是谁能把考点串成体系——这份26考点清单就是帮你建体系用的。