八股文 / 2026 春季

2026 年春季后端面经八股整理

本文汇总春季后端面经,共 45 道传统八股题。题目直接按技术类型归档,发布时间仅保留在每道题的来源标注中;Agent、LLM、RAG 与纯算法题不混入正文。

阅读时可以直接按自己的薄弱项进入 Java 与语言基础、JVM 与并发、操作系统、网络、数据库、缓存或分布式章节。

Java 与语言基础

1. Java 的基本数据类型有哪些?各占多少空间?

来源:神州信息后端开发岗,3 月 18 日

Java 有 8 种基本类型:byte 1 字节、short 2 字节、int 4 字节、long 8 字节、float 4 字节、double 8 字节、char 2 字节、boolean 的存储大小由 JVM 实现和使用场景决定,语言规范没有固定为 1 字节。包装类型是对象,会额外产生对象头、对齐和引用开销。


2. 重载和重写有什么区别?

来源:神州信息后端开发岗,3 月 18 日

重载发生在同一个类中,方法名相同但参数列表不同,编译期根据静态类型选择;仅改变返回值不能构成重载。重写发生在父子类之间,子类提供相同签名的方法实现,运行期通过动态分派选择实际对象的方法。重写不能缩小访问权限,也不能抛出比父类更宽的受检异常。


3. 类和接口怎么选?

来源:神州信息后端开发岗,3 月 18 日

接口表达能力契约,适合隔离实现、支持多实现和依赖倒置;抽象类适合共享稳定状态、受保护方法和模板流程。工程上通常优先面向接口并使用组合,只有存在稳定的 is-a 关系且确实需要复用状态或模板方法时才使用继承。


4. C++ 多态是如何实现的?

来源:恒生 C++ 一面,4 月 24 日

运行时多态依赖虚函数。含虚函数的对象通常保存虚表指针,虚表记录对应动态类型的函数地址;通过基类指针或引用调用虚函数时,运行期查表完成动态分派。构造和析构阶段的动态类型受限,基类析构函数应声明为虚函数,否则通过基类指针删除派生对象会产生未定义行为。


5. 智能指针怎么选?

来源:恒生 C++ 一面,4 月 24 日

unique_ptr 表达独占所有权,开销最小且支持移动;shared_ptr 通过控制块引用计数表达共享所有权,但原子计数和额外分配有成本;weak_ptr 不增加强引用计数,用于观察对象并打破环。默认先选 unique_ptr,只有生命周期确实共享时才用 shared_ptr,不要把智能指针当成可以忽略所有权设计的理由。


6. 重载和重写的区别是什么?

来源:线下 Java 小厂面经,5 月 14 日

重载是同一作用域中方法名相同、参数列表不同,调用目标在编译期确定;重写是子类重新实现父类可覆盖的方法,运行期按对象实际类型动态分派。重写要求签名兼容、访问权限不能更严格,返回类型只能相同或协变。静态方法是隐藏,不参与实例方法的动态分派。


7. HashMap 的底层结构和查找过程是什么?

来源:线下 Java 小厂面经,5 月 14 日

JDK 8 的 HashMap 由数组、链表和红黑树组成。先对 key 的 hash 做扰动,再用 (n - 1) & hash 定位桶;桶内比较 hash 和 equals。冲突过多且数组容量达到阈值时链表树化,扩容时容量翻倍,节点根据新增高位落在原位置或 原位置 + oldCap


8. HashMap 为什么线程不安全?

来源:线下 Java 小厂面经,5 月 14 日

并发写入时,桶插入、覆盖、size 更新和扩容迁移都不是一个原子事务,可能产生覆盖、丢失或读到中间状态。JDK 8 避免了旧版头插扩容易成环的问题,但没有让 HashMap 变成线程安全。并发读写应使用 ConcurrentHashMap,复合操作则使用 computemerge 等原子 API。


JVM 与并发

9. ThreadLocal 如何实现线程隔离?为什么会内存泄漏?

来源:快手 Java 后端一面,3 月 24 日

每个 Thread 持有自己的 ThreadLocalMapThreadLocal 实例作为 key,业务值作为 value,因此不同线程访问的是不同槽位。key 是弱引用,ThreadLocal 没有外部强引用后可能被回收;value 仍被线程强引用,线程池中的线程又长期存活,就会形成 key 为 null 的陈旧条目。正确做法是在 finally 中调用 remove(),同时避免在线程本地变量中保存大对象。


10. synchronizedReentrantLock 怎么选?

来源:快手 Java 后端一面,3 月 24 日

两者都提供互斥和可见性。普通临界区优先用 synchronized,语义简单且退出代码块会自动释放;需要可中断获取、超时、公平锁、多个 Condition 或非阻塞尝试时用 ReentrantLock。后者必须在 finally 中解锁。底层上,synchronized 依赖对象监视器和 JVM 优化,ReentrantLock 基于 AQS 状态与等待队列。


11. JVM 为什么需要垃圾回收?如何判断对象可回收?

来源:北京四维图新 Java 岗,3 月 6 日

GC 自动回收不可达对象,降低手工释放造成的泄漏、重复释放和悬空指针风险。HotSpot 主要从线程栈引用、静态字段、JNI 引用等 GC Roots 做可达性分析,不可达对象才成为候选。线上回答还应说明:GC 只能处理“不可达”,无界缓存或监听器持有对象仍然可达时,GC 无法替业务修复泄漏。


12. 互斥锁和读写锁分别适合什么场景?

来源:恒生 C++ 一面,4 月 24 日

互斥锁同一时刻只允许一个线程进入临界区,适合读写比例接近或临界区很短的场景。读写锁允许多个读者并发、写者独占,只有在读多写少且临界区足够大时才可能获益;写竞争、锁升级和饥饿会增加复杂度。选型应以基准测试和锁等待指标为准,而不是看到“读多”就机械替换。


13. JVM 如何完成垃圾回收?

来源:线下 Java 小厂面经,5 月 14 日

先从 GC Roots 做可达性分析,标记存活对象,再根据收集器采用复制、标记清除或标记整理。分代假说让新生代频繁回收短命对象,老年代处理长期存活对象;跨代引用通过记忆集减少全堆扫描。生产回答还应包含 GC 日志、分配速率、晋升、停顿和引用链分析,而不是只背收集器名称。


14. ThreadLocal 的正确使用方式是什么?

来源:京东 AI 应用开发岗,5 月 7 日

它适合保存一次线程执行链内的上下文,如 trace ID 或不可跨线程共享的会话状态。线程池会复用线程,所以必须在 finallyremove();异步任务切线程时,值不会自动正确传播,盲目使用可继承 ThreadLocal 还可能造成上下文污染。更清晰的方式是在边界显式传递上下文。


操作系统与 Linux

15. 进程、线程和协程有什么区别?

来源:腾讯后台一面,3 月 27 日

进程拥有独立地址空间,隔离强但创建和通信成本高;线程共享进程资源,内核调度,切换成本低于进程但要处理共享数据同步;协程由用户态运行时调度,适合大量 IO 等待任务。协程不会自动让 CPU 密集代码并行,仍受底层线程数量、语言运行时和 CPU 核数约束。


16. 为什么常说 CPython 多线程不能并行执行 Python 字节码?

来源:腾讯后台一面,3 月 27 日

CPython 的 GIL 让同一进程同一时刻通常只有一个线程执行 Python 字节码,简化了解释器对象内存管理。IO 阻塞和部分 C 扩展会释放 GIL,所以多线程仍适合 IO 密集任务;CPU 密集任务通常用多进程、释放 GIL 的扩展或支持自由线程的运行模式。不要把 GIL 误解成操作系统只能调度一个线程。


17. 线程、进程和协程的边界是什么?

来源:恒生 C++ 一面、蚂蚁效能研发一面,4 月 13–24 日

进程提供地址空间隔离,线程共享进程资源并由内核调度,协程则由用户态运行时在一个或多个线程上调度。进程崩溃隔离最好但 IPC 成本高;线程通信方便但需要同步;协程适合大量 IO 并发,但阻塞调用若没有被运行时接管,仍可能卡住承载线程。


18. 常用 Linux 排查命令怎么组织?

来源:美团 Java 后端一面,5 月 6 日

先看系统整体:uptimetopvmstat;再看进程和线程:pspidstat;查内存和磁盘:freeiostatdfdu;查网络和端口:sslsof;查日志:journalctltailrg。后台运行可使用 nohup command >app.log 2>&1 &,生产服务更应交给 systemd 或容器编排管理。


19. 进程和线程的区别是什么?

来源:线下 Java 小厂面经,5 月 14 日

进程是资源隔离和保护的基本单位,拥有独立虚拟地址空间;线程是 CPU 调度的执行单元,共享进程的代码、堆和文件描述符,但有自己的栈、寄存器和程序计数器。线程通信便宜但共享状态容易竞争,进程隔离强但 IPC 和切换成本更高。


网络、HTTP 与 RPC

20. OSI 七层模型和 TCP/IP 模型如何对应?

来源:网新软件后端二面,4 月 14 日

OSI 从下到上是物理、数据链路、网络、传输、会话、表示、应用;工程上常用 TCP/IP 四层:网络接口层、网际层、传输层、应用层。以 HTTPS 为例,以太网/Wi-Fi 承载链路帧,IP 负责路由,TCP 提供可靠字节流,TLS 负责加密认证,HTTP 定义应用语义。分层是职责抽象,不代表每个请求都由七个独立程序顺序处理。


21. SSE 和普通 Token 流式输出有什么区别?断线怎么恢复?

来源:Agent 小厂 Java 岗,4 月 9 日

SSE 是基于 HTTP 的服务端单向事件流;Token 流是业务内容粒度,可以承载在 SSE、WebSocket 或其他协议上。步骤级 SSE 应给每个事件分配递增 ID,并持久化任务状态;客户端重连时携带 Last-Event-ID,服务端重放缺失事件或返回当前快照。只保持内存连接不能跨实例、跨重启恢复。


22. 从输入 URL 到收到响应经历了什么?

来源:美团 Java 后端一面,5 月 6 日

客户端解析 URL 并检查缓存,经过 DNS 得到地址,再进行路由和 ARP/NDP,建立 TCP;HTTPS 还要完成 TLS 握手和证书校验。随后发送 HTTP 请求,经负载均衡、应用和存储处理后返回,浏览器再解析渲染。回答时要把 DNS、连接复用、TLS、网关和服务端处理串成因果链。


23. TLS 如何保证机密性、完整性和身份认证?

来源:美团 Java 后端一面,5 月 6 日

客户端验证服务端证书链和域名,双方通过密钥交换协商会话密钥,后续用对称加密保护数据,并用 AEAD 等机制校验完整性。现代 TLS 通常使用 ECDHE 提供前向保密。证书不是“用来加密所有业务数据”,它主要绑定身份和公钥;真正的大量数据使用协商出的对称密钥传输。


24. TIME_WAIT 为什么存在?

来源:美团 Java 后端一面,5 月 6 日

主动关闭方等待 2MSL,一是让最后 ACK 丢失后仍能响应对端重传 FIN,二是让旧连接的延迟报文消失,避免污染相同四元组的新连接。数量过多通常应先排查短连接、连接池和 keep-alive,而不是直接粗暴缩短内核参数。


25. RPC 和 HTTP 是什么关系?

来源:京东 Java 岗,5 月 7 日

HTTP 是应用层通信协议,RPC 是“像调用本地函数一样调用远端服务”的编程抽象。RPC 可以基于 HTTP/2,例如 gRPC,也可以使用私有协议;REST over HTTP 则更强调资源语义和跨语言可理解性。内部高性能强契约调用常用 RPC,对外开放和浏览器生态常用 HTTP API,但最终应按兼容性、治理和调试需求选型。


MySQL 与数据存储

26. 慢 SQL 的标准排查流程是什么?

来源:神州信息后端开发岗,3 月 18 日

先从监控和慢查询日志确认耗时分布、调用量和锁等待,再对代表性 SQL 使用 EXPLAINEXPLAIN ANALYZE 查看访问类型、实际行数、索引和临时表/排序。随后检查索引选择、回表次数、数据分布、隐式转换、深分页和事务持锁。优化后必须用相同数据量压测并观察 P95/P99,不能只看单次执行时间。


27. 联合索引为什么遵循最左前缀?

来源:快手 Java 后端一面,3 月 24 日

B+ 树按联合索引定义的列顺序排序,例如 (a,b,c) 先按 a,再按 b,最后按 c。因此只查 b 时,全局上并没有按 b 排序,通常不能完成有效定位。a=? AND b>? 可以利用 a,b 定位范围,但范围列之后的列通常不能继续缩小扫描边界,是否可下推过滤要看执行计划。


28. ACID 分别由什么机制支撑?

来源:网新软件后端二面,4 月 14 日

原子性依赖 undo log 回滚;隔离性依赖锁和 MVCC;持久性依赖 redo log 的 WAL 和刷盘策略;一致性是事务机制、数据库约束和业务规则共同作用的结果。回答时要避免说“redo log 保证原子性”这类错位,也要说明不同刷盘参数会在性能与故障丢失窗口之间取舍。


29. MyBatis 的 #{}${} 有什么区别?

来源:网新软件后端二面,4 月 14 日

#{} 使用预编译参数占位,驱动负责类型转换,通常能避免 SQL 注入;${} 是文本替换,适合无法参数化的表名、列名或排序方向,但必须使用白名单映射,不能直接拼用户输入。动态 SQL 的重点不是“能拼出来”,而是参数安全、可读性和执行计划稳定性。


30. MySQL 为什么使用 B+ 树索引?

来源:恒生 C++ 一面,4 月 24 日

B+ 树内部节点只存键和子指针,同一页能容纳更多分支,树高更低;完整记录集中在叶子节点,叶子又按序相连,点查、范围扫描和排序都较稳定。InnoDB 聚簇索引叶子存整行,二级索引叶子存主键,因此查询非覆盖列通常需要回表。


31. PostgreSQL JSONB、Redis 和关系表怎么选?

来源:Agent 小厂 Java 岗,4 月 9 日

JSONB 适合结构变化较快但仍需要事务、持久化和字段索引的状态;Redis 适合低延迟临时状态、TTL 和队列,但内存成本高且持久化语义需明确;关系表适合字段稳定、约束和关联查询强的核心数据。选型取决于查询模式、生命周期、一致性和恢复目标,而不是只比较单次读写速度。


32. MySQL 主从复制的基本流程是什么?

来源:美团 Java 后端一面,5 月 6 日

主库提交事务并写 binlog,从库 IO 线程拉取事件写 relay log,SQL 线程或并行复制线程回放。异步复制吞吐好但主库故障时可能丢未同步数据;半同步只保证至少一个从库收到日志,不等于已经执行。读写分离还要处理复制延迟和读己之写问题。


Redis 与缓存

33. Redis 为什么快?

来源:快手 Java 后端一面,3 月 24 日

核心原因是数据主要在内存中、命令执行路径短、数据结构针对场景优化,并用 IO 多路复用处理大量连接。经典命令执行采用单线程,避免共享数据的锁竞争;Redis 6 之后可用多线程处理网络读写,但命令执行仍以串行为主。大 Key、慢命令、阻塞式删除和持久化抖动仍可能拖慢整个实例。


34. 缓存穿透是什么?怎么治理?

来源:腾讯后台一面,3 月 27 日

缓存穿透是持续查询不存在的数据,请求每次绕过缓存落到数据库。治理顺序通常是参数校验和鉴权、对空结果设置较短缓存、用布隆过滤器挡住确定不存在的 key,再配合限流和异常流量识别。布隆过滤器存在误判且不擅长删除,不能替代数据库校验。


35. Redis 哨兵能解决什么问题?

来源:神州信息后端开发岗,3 月 18 日

Sentinel 负责监控主从节点、通过多数 Sentinel 完成客观下线判断、选举领导者并执行主从切换,同时向客户端提供新主节点地址。它解决高可用,不解决水平分片;容量和写吞吐需要 Redis Cluster 或业务分片。异步复制还意味着故障切换时可能丢失尚未同步的数据。


36. 缓存和数据库如何保证最终一致?

来源:网新软件后端二面,4 月 14 日

常用 Cache Aside:读时先查缓存,未命中查数据库并回填;写时先提交数据库,再删除缓存。删除失败要进入可靠重试或通过 binlog/CDC 异步补偿。高并发热点还要防止旧请求在写后回填旧值,可结合版本号、短 TTL 或串行化热点更新。延迟双删不是万能公式,延迟量必须有业务依据。


37. Redis 为什么快,但仍然可能成为瓶颈?

来源:美团后端一面,4 月 23 日

Redis 依靠内存访问、高效结构、IO 多路复用和短命令路径获得低延迟。瓶颈常来自大 Key、KEYS 或复杂集合运算等慢命令、热 Key、网络带宽、持久化 fork/写盘以及内存碎片。排查应看命令延迟、慢日志、Key 分布、CPU、网络和 fork 耗时,不能只回答“单线程所以快”。


分布式与工程设计

38. 分布式事务有哪些常见方案?

来源:北京四维图新 Java 岗,3 月 6 日

强一致且参与者少时可考虑 XA/2PC,但锁持有时间长、协调者和可用性成本高。业务系统更常用 TCC、Saga 或本地事务 + Outbox/消息最终一致:本地事务原子写业务数据和事件,再异步投递,下游依赖幂等消费、重试、对账和补偿。选型先明确一致性目标,不能只说“上分布式事务框架”。


39. 一个服务从开发到上线要经过哪些环节?

来源:北京四维图新 Java 岗,3 月 6 日

需求与接口评审后完成设计、编码、单元/集成测试和安全扫描,构建不可变制品,经测试环境验证后采用灰度或蓝绿发布。上线阶段要有配置与数据库变更顺序、健康检查、监控告警、容量基线、回滚条件和负责人。发布完成还要观察错误率、延迟、资源水位和核心业务指标,而不是“容器启动成功”就结束。


40. 新增数据如何保证幂等?

来源:Agent 小厂 Java 岗,4 月 9 日

先定义业务唯一键,例如订单号或请求号,并在数据库建立唯一约束,这是并发下最后的正确性防线。入口可用幂等 token 或 Redis SET NX 降低重复请求,但不能只依赖缓存;写入时捕获唯一键冲突并返回已有结果。涉及多步骤时还要用状态机限制合法流转,并让重试可以安全恢复。


41. 常见设计模式如何避免为了模式而模式?

来源:恒生 C++ 一面,4 月 24 日

策略模式适合在运行时替换算法,责任链适合让多个处理器按顺序尝试,工厂适合隔离对象创建,观察者适合一对多事件通知。回答必须落到变化点:哪个依赖需要隔离、扩展时减少了哪些修改、引入了什么调试和调用链成本。没有稳定变化方向时,直接代码往往更清晰。


42. 服务降级、熔断和限流分别解决什么问题?

来源:美团 Java 后端一面,5 月 6 日;京东 Java 岗,5 月 7 日

限流控制进入系统的请求速率,保护容量;熔断在下游持续失败时快速失败,阻止故障放大;降级在资源不足或依赖不可用时关闭非核心能力、返回兜底。三者通常组合使用,并配合超时、隔离、重试预算和监控。没有超时边界的重试会制造流量放大。


43. 常见限流算法怎么选?

来源:京东 Java 岗,5 月 7 日

固定窗口简单但有边界突刺;滑动窗口更平滑但状态更多;漏桶严格匀速,适合保护固定吞吐的下游;令牌桶允许受控突发,适合多数 API。分布式限流可用 Redis + Lua 保证单次判断原子性,但还要明确时钟、故障降级、热点 key 和多机本地配额误差。


44. 如何设计请求幂等?

来源:小红书 Java 岗,5 月 5 日

为请求分配业务唯一 ID,在数据库建立唯一约束,并保存处理结果;重复请求命中相同 ID 时直接返回既有结果。Redis SET NX 可以减轻重复执行,但必须设置合理过期并考虑处理超时后的恢复。支付、订单等状态变更还要使用状态机、乐观锁和对账补偿。


45. 为什么在异步事件场景选择 Redis Streams?

来源:阿里国际暑期实习一面,5 月 3 日

Streams 提供持久化消息、消费者组、待确认列表和显式 ACK,比 Pub/Sub 更适合需要恢复和重试的轻量事件流;同时运维成本低,适合系统已经依赖 Redis 且吞吐规模可控的场景。它不能直接等同于 Kafka:分区扩展、超长保留、跨机房复制和大规模消费生态较弱。选型要说明消息量、保留周期、丢失容忍度和失败恢复。

下一篇建议继续看: