OfferGod

Java 后端开发面试常见问题有哪些?怎么准备(校招 / 社招)

一句话概括

Java 后端面试基本围着七块转——Java 基础与集合、并发、JVM、Spring、MySQL、缓存与消息队列、分布式与系统设计,再加上一轮绕不开的项目深挖。校招看基础扎不扎实、代码写不写得出来、学东西快不快;社招看你处理过什么线上问题、做过什么技术取舍、系统量上来之后扛不扛得住;转行的同学则要用一个能讲透的完整项目,证明自己已经能干活。

  • 26 道高频题
  • 阅读约 39 分钟
  • 内容核对于 2026-10-20

01这个岗位是做什么的?

Java 后端工程师负责用户看不见、但每一次点击都要经过的那一层:接收前端或 App 发来的请求,做业务逻辑处理,读写数据库和缓存,调用其他服务,再把结果返回回去。日常工作大致是:和产品对需求、设计接口和表结构、写业务代码和单元测试、联调、发布上线,然后盯监控、处理告警、排查线上问题。

常见方向有三类,面试侧重点会跟着变:

  • 业务后端:电商交易、内容社区、营销活动、企业 SaaS、金融科技的业务系统等,最常见。重点考 Spring 全家桶熟练度、数据库设计、接口设计,以及对业务的理解——比如订单状态怎么流转、重复下单怎么防。
  • 中间件 / 平台研发:消息队列、RPC 框架、配置中心、网关、任务调度、数据库中间件等。会深挖并发、网络 IO、JVM 和源码,对「为什么这么设计」的追问更多。
  • 基础架构 / 稳定性方向:容器与发布平台、监控告警、全链路压测、容量规划。会问高可用设计、故障处理流程、可观测性。

级别上大致是:实习 / 初级(能按设计写好接口、写测试、修 bug)→ 中级(独立负责一个模块,从表结构到上线全流程,能处理常见线上问题)→ 高级 / 资深(负责一个系统的设计和稳定性,做容量评估和技术选型,带新人)→ 专家 / 负责人(跨系统、跨团队的架构规划)。级别越高,面试越少问「这个注解怎么用」,越多问「数据量翻十倍你怎么办」「出了故障你怎么兜底」。

02JD 怎么读?

后端 JD 的套话看起来都差不多,但每一句背后都对应着一类面试题。拿到 JD 先按下表拆一遍,就知道哪里要准备到原理层,哪里会用就行。

典型 JD 要求面试官会怎么考你该准备什么
Java 基础扎实,熟悉集合、并发编程HashMap 结构与扩容、ConcurrentHashMap、锁、线程池参数、volatile每个知识点能讲到「为什么这样设计」;线程池能结合自己项目说出参数怎么定的
熟悉 JVM,有调优经验内存区域、垃圾回收器选择、OOM 和 Full GC 怎么排查背熟内存区域只是起点;准备一次自己动手的排查过程(哪怕是本地复现的)
熟悉 Spring / Spring BootIoC、AOP、Bean 生命周期、事务失效场景、自动配置原理能用自己的话讲清代理机制;把 @Transactional 的失效场景亲手试一遍
熟悉 MySQL,有 SQL 调优经验索引结构、索引失效、执行计划、隔离级别与 MVCC、锁会看 EXPLAIN 的关键列;准备 1 个有前后对比的慢 SQL 优化案例(数据用你自己的)
熟悉 Redis 等缓存数据结构的使用场景、穿透击穿雪崩、缓存与数据库一致性、过期与淘汰说清项目里缓存了什么、过期时间怎么定、数据不一致时怎么兜底
熟悉消息队列(Kafka 等 等)为什么引入 MQ、消息丢失与重复、顺序消息、积压怎么处理画出你项目里消息的生产、存储、消费链路,标出每一步可能丢消息的地方
有高并发、分布式系统经验(社招常见)系统设计题、分布式锁、分布式事务、限流熔断降级、分库分表准备一个「量上来之后我们怎么改」的完整故事:瓶颈在哪、方案对比、效果数据
有良好的编码习惯和工程意识代码规范、单元测试、Code Review、日志与异常处理、接口幂等能说出团队实际执行的规范,以及你因为某个规范避免过的坑
有责任心、沟通协作能力和产品、前端、测试的分歧怎么处理;线上故障中你的角色;带新人(社招)准备 2–3 个 STAR 结构的真实经历,其中一个最好是线上问题

小技巧:JD 里写的「加分项」(如 Go、云原生、大数据组件、搜索引擎)不一定考,但如果你真的用过,在自我介绍里主动提一句,给面试官一个追问的抓手;没用过就别写在简历上。

03面试一般几轮、每轮考什么?

不同公司轮次不完全一样,常见结构如下,具体以招聘方通知为准:

轮次主要考什么时长参考准备建议
笔试 / 在线编程(校招多见)算法编程题 + 少量 Java、数据库、操作系统、网络选择题60–120 分钟按类型刷简单到中等难度算法题;熟悉在线判题环境的输入输出写法
技术一面Java 基础、集合、并发、JVM、MySQL、Redis 等基础知识 + 手写代码 + 简历初问45–60 分钟概念题答到「为什么」;手写题边写边说思路和边界
技术二面深挖项目、线上问题、技术取舍,可能有一道开放的系统设计题45–75 分钟项目里每个技术点准备被追问三层;系统设计按「需求—估算—设计—扩展」走
业务面 / 主管面业务理解、技术视野、协作方式、成长潜力30–60 分钟准备「最难的事」「做错过什么」「为什么想做后端 / 为什么换工作」
交叉面(社招中高级岗位可能有)其他团队的人再评估一次,常偏架构和综合能力45–60 分钟把核心项目的架构图能在白纸上画出来并讲清楚
HR 面动机、稳定性、团队协作、期望薪资、到岗时间20–40 分钟离职原因、为什么选这里、期望薪资提前想好,口径前后一致

社招常见的变化:算法题比重下降,一面就可能直接深挖项目;系统设计和线上问题复盘比重明显上升;高级岗位可能出现架构评审式的面试,让你讲一个自己负责的系统的全貌。实习面试一般是 2–3 轮技术加 1 轮 HR,难度比正式校招略低,但基础题和手写代码一样会考。转行的同学按社招或校招通道走都有可能,面试官会更关注你的项目是不是自己真正做出来的。

04高频题有哪些?怎么答?

题型
轮次
招聘类型
  1. 01HashMap 的底层结构是什么?扩容时发生了什么?专业知识技术一面校招 · 实习 · 社招基础

    考察点: 最常见的集合题,看你是只背了结论,还是理解了设计取舍。

    答题思路:

    • 结构(以 JDK 8 及之后为准):一个数组,每个位置叫一个桶;哈希冲突的元素先用链表挂在桶上,链表过长且数组容量足够大时转成红黑树,把最坏情况下的查找从线性降到对数级。
    • 定位过程:先算 key 的 hashCode,再把高位和低位做一次异或扰动,然后用「哈希值 & (容量 - 1)」算下标。容量保持为 2 的幂,就是为了让这个与运算等价于取模且更高效。
    • 扩容:元素个数超过「容量 × 负载因子」(默认负载因子 0.75)就扩容为原来的两倍。迁移时每个元素要么留在原下标,要么移动到「原下标 + 旧容量」,只需看哈希值多出来的那一位,不用重新计算完整哈希。
    • 树化细节:链表长度达到阈值且数组容量达到一定值才会树化,容量小的时候优先扩容;具体阈值以所用 JDK 版本源码为准。
    • 线程不安全的表现:并发 put 可能丢数据、size 不准;老版本 JDK 并发扩容时还可能形成环形链表导致死循环。多线程场景用 ConcurrentHashMap。

    校招怎么答 / 社招怎么答: 校招讲清结构、下标计算、扩容迁移和线程不安全就够;社招可以补一句实践经验,比如已知数据量时初始化给足容量,避免反复扩容,以及排查过的「对象作为 key 时 hashCode 被修改导致取不出来」这类问题。

    可能的追问: 为什么负载因子取 0.75 而不是 1?为什么用红黑树而不是平衡二叉树或跳表?HashMap 允许 null 键吗?

    练一练
  2. 02ArrayList 和 LinkedList 有什么区别?实际开发怎么选?专业知识技术一面校招 · 实习基础

    考察点: 数据结构基本功,以及会不会被「教科书结论」带偏。

    答题思路:

    • ArrayList 底层是动态数组,按下标随机访问快;在中间插入或删除要移动后面的元素;容量不够时按约 1.5 倍扩容并拷贝数组。
    • LinkedList 是双向链表,按下标访问要从头或尾遍历;已经拿到节点位置时插入删除快;每个节点额外存两个指针,内存占用更大。
    • 实际选择:大多数业务场景用 ArrayList。原因是数组内存连续、对 CPU 缓存友好,而 LinkedList 想在中间插入也得先遍历找到位置,理论上的优势在实践中常常体现不出来。
    • 需要队列或双端队列时,优先考虑 ArrayDeque。

    可能的追问: ArrayList 遍历时删除元素为什么会抛 ConcurrentModificationException?怎么正确删除?

    练一练
  3. 03为什么重写 equals 时一定要重写 hashCode?专业知识技术一面校招 · 实习基础

    考察点: 是否理解哈希容器的约定。

    答题思路:

    • 约定:两个对象 equals 为 true,hashCode 必须相等;hashCode 相等,equals 不一定为 true(哈希冲突)。
    • 只重写 equals 不重写 hashCode:两个「逻辑上相等」的对象哈希值不同,放进 HashMap / HashSet 会落到不同的桶,结果是 Set 里出现重复元素、Map 里用新对象当 key 取不到值。
    • 实践:用 IDE 或 Objects.hash 一起生成;参与计算的字段最好是不可变的,否则对象放进集合后字段一改,就再也找不到它了。
    • Java 16 起的 record 会自动按字段生成这两个方法,可以顺带提一句。

    可能的追问: == 和 equals 有什么区别?String 的 hashCode 是怎么算的、为什么会缓存?

    练一练
  4. 04String 为什么设计成不可变的?String、StringBuilder、StringBuffer 怎么选?专业知识技术一面校招 · 实习基础

    考察点: 对语言设计取舍的理解。

    答题思路:

    • 不可变的好处:字符串常量池可以安全地共享同一个对象;天然线程安全;哈希值可以缓存,适合做 HashMap 的 key;作为类名、文件路径、连接参数传递时不会被中途篡改,更安全。
    • 「不可变」的实现:类用 final 修饰不能被继承,内部存储字符的数组是私有且不对外暴露修改方法。
    • 选择:少量拼接直接用 +(编译器会优化);循环里大量拼接用 StringBuilder;StringBuffer 方法加了同步,多线程共享同一个对象拼接时才需要,实际很少用。
    • 可以提一句:JDK 9 起 String 内部从 char[] 改为 byte[] 加编码标记,纯 Latin-1 字符串更省内存。

    可能的追问: new String("abc") 创建了几个对象?intern() 有什么用、有什么风险?

    练一练
  5. 05synchronized 和 ReentrantLock 有什么区别?专业知识技术一面校招 · 社招进阶

    考察点: 并发基础核心题,看你对锁的理解深度。

    答题思路:

    • 实现层面:synchronized 是 JVM 层面的关键字,基于对象头和监视器实现,进出代码块由 JVM 自动加锁解锁;ReentrantLock 是 JDK 提供的类,基于 AQS(抽象队列同步器)实现,需要手动 lock 并在 finally 里 unlock。
    • 功能差异:ReentrantLock 支持可中断地等锁(lockInterruptibly)、尝试加锁和超时(tryLock)、公平锁、多个条件变量(Condition);synchronized 只能用 wait / notify 配合一个等待队列。
    • 共同点:都是可重入锁。
    • 性能:JVM 对 synchronized 做了很多优化(轻量级锁、自旋、锁消除、锁粗化),一般场景下性能差距不大,选择主要看功能需要。偏向锁在较新的 JDK 中已默认关闭并逐步移除,讲锁升级时注意版本。
    • 选择建议:简单互斥用 synchronized,代码更不容易出错;需要超时、可中断、公平或多条件时用 ReentrantLock。

    校招怎么答 / 社招怎么答: 校招讲清区别和 AQS 的基本思路(一个 state 加一个等待队列);社招可以讲一次因为锁使用不当导致的问题,比如锁粒度太大导致接口变慢,或者 unlock 没放在 finally 里导致的线程卡死。

    可能的追问: AQS 的核心原理是什么?公平锁和非公平锁哪个吞吐更高、为什么?什么是死锁、怎么排查?

    练一练
  6. 06线程池的核心参数有哪些?任务提交后的执行流程是什么?参数怎么设?专业知识技术一面技术二面校招 · 社招进阶

    考察点: 不只是背参数,而是能否结合业务设置并说出风险。几乎每场后端面试都会碰到。

    答题思路:

    • 七个参数:核心线程数、最大线程数、非核心线程空闲存活时间及单位、任务队列、线程工厂、拒绝策略。
    • 执行流程:线程数小于核心数就新建线程执行;否则放进队列;队列满了且线程数小于最大数就新建非核心线程;都满了就执行拒绝策略。注意顺序是「先进队列、再扩线程」,这一点经常被说反。
    • 四种内置拒绝策略:抛异常(默认)、由提交任务的线程自己执行、直接丢弃、丢弃队列里最老的任务。
    • 参数估算思路:CPU 密集型任务线程数接近 CPU 核数;IO 密集型可以更多,大致按「核数 × (1 + 等待时间 / 计算时间)」估算。但这只是起点,最终要靠压测和监控调整。
    • 风险点:用 Executors 的快捷方法创建的固定线程池使用无界队列,任务堆积可能导致内存溢出;生产环境建议手动创建,用有界队列,给线程起有意义的名字,方便排查。

    示范回答(校招版):

    线程池有七个参数:核心线程数、最大线程数、空闲线程存活时间和单位、任务队列、线程工厂和拒绝策略。提交任务时,如果当前线程数还没到核心数,就直接新建线程执行;到了核心数,任务先放进队列;队列也满了,再看线程数有没有到最大值,没到就创建非核心线程;全都满了就走拒绝策略,默认是直接抛异常。参数怎么设要看任务类型,计算多的任务线程数接近 CPU 核数就行,开多了反而切换开销大;像调接口、读数据库这种等待多的任务可以多开一些。我在【课程项目 / 实习项目】里用线程池并行调用【3 个】查询接口,一开始直接用了 Executors 的固定线程池,后来了解到它的队列是无界的,请求多的时候任务会一直堆积,就改成了手动创建,用了容量为【200】的有界队列,拒绝策略选了让调用线程自己执行,这样压力大时请求会变慢,但不会把内存撑爆。

    示范回答(社招版):

    参数和流程我简单过一下:线程数没到核心数就建线程,到了就进队列,队列满了再扩到最大线程数,再满就拒绝。我想重点说一下我们在【某个聚合查询服务】里是怎么定参数的。这个接口要并行调【N 个】下游,属于典型的 IO 密集型。我们先按「核数 × (1 + 等待时间 / 计算时间)」估了一个初始值,然后在压测环境逐步加压,盯三个指标:线程池活跃线程数、队列长度、接口的较慢分位耗时,最后把核心线程数定在【X】,队列容量【Y】。拒绝策略没用默认的抛异常,而是自定义成记录日志、打点报警,再返回降级结果,因为这个接口允许部分数据缺失。另外我们踩过两个坑:一是多个业务共用一个线程池,其中一个下游变慢把线程全占满,导致其他业务一起超时,后来按业务做了线程池隔离;二是线程池参数写死在代码里,调整要发版,后来接入了配置中心支持动态调整核心数和最大线程数,并把线程池的运行指标接进了监控大盘。

    可能的追问: 核心线程会被回收吗?线程池里的任务抛异常了会怎样?怎么优雅地关闭线程池?CompletableFuture 默认用的是哪个线程池、有什么风险?

    练一练
  7. 07volatile 能保证什么?不能保证什么?专业知识技术一面校招 · 实习进阶

    考察点: 对 Java 内存模型的理解。

    答题思路:

    • 能保证可见性:一个线程修改了 volatile 变量,其他线程能立刻读到最新值,而不是读自己工作内存里的旧副本。
    • 能保证有序性:通过内存屏障禁止特定的指令重排序。经典例子是双重检查锁单例里,实例变量必须加 volatile,否则其他线程可能拿到一个「已分配内存但还没初始化完」的对象。
    • 不能保证原子性:count++ 是「读—改—写」三步,多个线程同时执行仍会丢失更新。需要用 synchronized、锁或 AtomicInteger 这类原子类。
    • 典型用法:状态标志位(比如控制线程停止的开关)、双重检查锁单例。

    可能的追问: 什么是 happens-before 原则?AtomicInteger 是怎么保证原子性的?CAS 有什么问题(ABA、自旋开销)?

    练一练
  8. 08ConcurrentHashMap 是怎么做到线程安全的?专业知识技术一面技术二面社招 · 校招进阶

    考察点: 并发容器的设计思想,社招常问。

    答题思路:

    • 老版本(JDK 7):分段锁,把整个表分成若干段,每段一把锁,不同段之间可以并发写。
    • JDK 8 及之后:取消分段,结构和 HashMap 类似。写入时如果桶是空的,用 CAS 直接放入;桶不为空时,只对这个桶的头节点加 synchronized,锁粒度细到单个桶。
    • 读操作基本不加锁,依赖 volatile 保证可见性。
    • 扩容时支持多个线程协助迁移数据。
    • size 的统计:用一个基础计数加上一组分散的计数单元,竞争激烈时把累加分散到不同单元,最后求和,思路和 LongAdder 类似,所以 size 是一个近似的瞬时值。
    • 和 Hashtable 对比:后者整个表一把锁,并发性能差,基本不再使用。

    可能的追问: ConcurrentHashMap 为什么不允许 null 键和 null 值?「先 get 判断再 put」这种复合操作安全吗、应该用什么方法?

    练一练
  9. 09JVM 内存分哪几块?哪些地方会发生内存溢出?专业知识技术一面校招 · 社招基础

    考察点: JVM 基础,以及能否和线上问题联系起来。

    答题思路:

    • 线程共享:堆(对象实例,垃圾回收的主要区域)、方法区(类信息、常量、静态变量;JDK 8 起用本地内存中的元空间实现,替代了永久代)。
    • 线程私有:虚拟机栈(每个方法调用一个栈帧,存局部变量等)、本地方法栈、程序计数器。
    • 堆外:直接内存(NIO 等使用),不受堆大小参数限制,但有单独的上限。
    • 对应的问题:堆满了报堆空间不足的 OOM,常见原因是内存泄漏或一次加载数据过多;元空间满了常见于动态生成大量类;栈太深报 StackOverflowError,常见于无终止条件的递归;线程创建过多可能报无法创建本地线程;直接内存不足多见于网络框架使用不当。
    • 程序计数器是唯一不会发生 OOM 的区域,可以顺带一提。

    校招怎么答 / 社招怎么答: 校招讲清分区和每块存什么;社招一定要带上「我遇到过哪种 OOM、怎么定位的」,比如通过堆转储文件发现是某个缓存没设上限。

    可能的追问: 对象一定分配在堆上吗(逃逸分析)?对象从新生代晋升到老年代的条件有哪些?

    练一练
  10. 10常见的垃圾回收器有哪些?项目里怎么选?专业知识技术二面社招进阶

    考察点: 是否理解吞吐量和停顿时间的取舍,而不是只会背回收器名字。

    答题思路:

    • 先讲基础:分代思想(大部分对象朝生夕死)、可达性分析判断对象存活、标记—清除 / 标记—复制 / 标记—整理三类算法各自的优缺点。
    • 回收器按目标分:Serial(单线程,适合小内存客户端);Parallel(关注吞吐量,适合后台批处理);G1(把堆划成很多大小相等的区域,优先回收垃圾最多的区域,可以设定期望停顿时间,在 JDK 9 起作为服务端默认回收器);ZGC、Shenandoah(目标是极低停顿,适合大堆、对延迟敏感的服务)。CMS 已在较新版本中移除。
    • 选择思路:先明确业务目标——接口服务通常更在乎停顿时间,离线任务更在乎吞吐量;再看堆大小和 JDK 版本;最后用 GC 日志和压测验证,而不是凭感觉改参数。
    • 以所用 JDK 版本的官方调优文档为准。

    可能的追问: G1 的一次混合回收大致经历哪些阶段?什么情况下会触发 Full GC?你看过 GC 日志吗、看哪些指标?

    练一练
  11. 11线上某个服务 CPU 突然飙高或者频繁 Full GC,你怎么排查?情景应变技术二面社招深挖

    考察点: 线上问题处理的方法论和实际动手经验,社招重点题。

    答题思路:

    • 第一步先止血:看影响范围,必要时摘流量、扩容、回滚最近的发布或重启部分实例,但重启前先保留现场(线程栈、堆转储、GC 日志)。
    • CPU 高的定位:用 top 找到进程,再看进程内哪个线程占 CPU 高,把线程号转成十六进制,用 jstack 或 jcmd 进程号 Thread.print 导出线程栈,找到对应线程在执行什么代码。常见原因是死循环、大量正则或序列化计算、频繁 GC 本身占满 CPU。
    • Full GC 频繁的定位:用 jstat 观察各区的使用和 GC 次数,看老年代是不是回收后也降不下来;用 jmap 或 jcmd 导出堆转储,用内存分析工具看哪些对象占得最多、被谁引用着。常见原因是内存泄漏(静态集合不断增长、缓存没上限)、一次查询加载过多数据、大对象频繁创建。
    • 也可以用 JDK 自带的飞行记录器(JFR)做低开销的持续采样。
    • 最后讲修复和复盘:根因是什么、怎么修、补了哪些监控和告警、以后怎么避免。

    校招怎么答 / 社招怎么答: 校招如果没有线上经历,可以说清排查思路,再讲一次在本地故意写个死循环或内存泄漏、用工具定位到的练习;社招要讲一次真实的排查经过,时间线、用了什么命令、看到了什么现象、最终根因,数字用你自己的。

    可能的追问: 堆转储文件很大、线上不方便导出怎么办?如果是内存泄漏,怎么判断是哪个对象泄漏?

    练一练
  12. 12用你自己的话讲讲 Spring 的 IoC 和 AOP。专业知识技术一面校招 · 实习基础

    考察点: 是否真的理解,而不是背定义。

    答题思路:

    • IoC(控制反转):对象不再自己 new 依赖,而是交给容器创建和组装,容器把依赖「注入」进来(依赖注入是 IoC 的实现方式)。好处是解耦:换一个实现类只改配置,不改调用方;也方便写单元测试时替换成模拟对象。
    • 推荐构造器注入:依赖不可变、不会出现空指针、依赖过多时一眼就能看出这个类职责太重。
    • AOP(面向切面编程):把日志、事务、权限、监控这类横跨很多业务方法的逻辑抽出来,统一织入,业务代码只关心业务本身。
    • AOP 的实现:运行时生成代理对象。目标类实现了接口时可以用 JDK 动态代理,否则用基于子类的代理(CGLIB 方式);Spring Boot 默认倾向于使用基于类的代理,以所用版本配置为准。
    • 结尾带一句你用 AOP 做过什么,比如统一的接口耗时日志或操作审计。

    可能的追问: Bean 的生命周期大致有哪些阶段?Spring 是怎么解决循环依赖的、为什么构造器注入的循环依赖解决不了?

    练一练
  13. 13@Transactional 在哪些情况下会失效?专业知识技术一面技术二面校招 · 社招进阶

    考察点: 是否在项目里真正踩过坑,以及对代理机制的理解。

    答题思路:

    • 根本原因:Spring 事务基于代理实现,只有通过代理对象调用方法时,事务逻辑才会生效。顺着这个思路就能推出大部分失效场景。
    • 同一个类里的方法自调用:this.methodB() 绕过了代理,methodB 上的事务注解不生效。
    • 方法不是 public:在常见的代理配置下不生效(较新版本对基于类的代理有放宽,以所用版本为准)。
    • 异常被吞了:方法内部 try / catch 后没有重新抛出,事务管理器感知不到异常,不会回滚。
    • 异常类型不对:默认只对运行时异常和 Error 回滚,受检异常不回滚,需要配置 rollbackFor。
    • 传播行为配置:比如被调用方法配置成不支持事务或新开事务,行为和预期不同。
    • 其他:类没有被 Spring 管理;在新线程里执行数据库操作(不在同一个事务上下文);数据库表引擎本身不支持事务。
    • 实践建议:事务范围尽量小,不要在事务里调用远程接口或做耗时操作,否则长时间占用数据库连接。

    可能的追问: 七种传播行为里最常用的是哪几种、REQUIRED 和 REQUIRES_NEW 的区别?大事务会带来什么问题?

    练一练
  14. 14Spring Boot 的自动配置是怎么生效的?专业知识技术二面社招 · 校招进阶

    考察点: 是否理解「约定优于配置」背后的机制,排查问题时用得上。

    答题思路:

    • 入口:启动类上的组合注解开启了自动配置。
    • 加载:Spring Boot 从各个依赖包里约定位置的清单文件读取自动配置类列表(较新版本用专门的 AutoConfiguration.imports 文件,早期版本用 spring.factories)。
    • 条件生效:自动配置类上带着条件注解,比如「类路径上存在某个类才生效」(@ConditionalOnClass)、「用户自己没定义这个 Bean 才生效」(@ConditionalOnMissingBean)、「某个配置项打开才生效」。所以引入一个 starter 依赖,相关组件就自动配好了;用户自己定义了 Bean,默认的就让路。
    • 排查技巧:启动时开启 debug 模式能打印条件评估报告,看到哪些自动配置生效、哪些没生效、为什么;也可以用 Actuator 的相关端点查看。
    • 加分:说一下你写过的自定义 starter,或者解决过的自动配置冲突(比如多数据源时默认数据源配置的冲突)。

    可能的追问: starter 是怎么组织的?配置文件的加载顺序和优先级是怎样的?

    练一练
  15. 15MySQL 的索引为什么用 B+ 树?什么情况下索引会失效?专业知识技术一面校招 · 社招基础

    考察点: 数据库必考题,看能否把结构和使用联系起来。

    答题思路:

    • 为什么是 B+ 树(以 InnoDB 为准):数据在磁盘上,查询瓶颈是磁盘 IO 次数。B+ 树是多叉树,每个节点能存很多键,树很矮,几次 IO 就能定位到数据;非叶子节点只存键不存数据,能放更多键;叶子节点之间有链表连接,范围查询和排序很方便。对比哈希索引不支持范围查询,对比二叉树层数太高。
    • 聚簇索引和二级索引:InnoDB 的主键索引叶子节点存整行数据;二级索引叶子节点存主键值,查其他列要回表。查询的列都在索引里就能避免回表,叫覆盖索引。
    • 常见失效场景:联合索引不满足最左前缀;在索引列上用函数或运算;隐式类型转换(比如字符串列用数字去比较);LIKE 以通配符开头;OR 连接的条件里有列没有索引;优化器判断走索引还不如全表扫描(比如区分度很低的列)。
    • 验证方法:用 EXPLAIN 看 type、key、rows、Extra 这几列,而不是凭感觉判断。

    校招怎么答 / 社招怎么答: 校招讲清结构、回表、最左前缀和几种失效场景;社招结合一次真实的索引设计,比如为某个高频查询建了什么联合索引、字段顺序为什么这样排。

    可能的追问: 主键为什么建议用自增 ID 而不是 UUID?索引是不是越多越好?什么是索引下推?

    练一练
  16. 16事务的隔离级别有哪些?MVCC 是怎么实现的?专业知识技术一面技术二面校招 · 社招进阶

    考察点: 对并发事务问题的理解。

    答题思路:

    • 四种隔离级别和对应问题:读未提交(可能脏读)、读已提交(避免脏读,可能不可重复读)、可重复读(避免不可重复读,标准定义下可能幻读)、串行化(全部避免,并发性能差)。InnoDB 默认是可重复读。
    • MVCC(多版本并发控制)的核心:每行记录带有最近修改它的事务 ID 和指向旧版本的指针,旧版本存在 undo 日志里,串成一条版本链。
    • 读视图(Read View):事务读数据时生成一个「快照」,记录当时哪些事务还没提交,沿着版本链找到对自己可见的那个版本。读已提交每次查询都生成新的读视图;可重复读在事务第一次查询时生成,之后一直复用,所以多次读结果一致。
    • 快照读和当前读:普通 SELECT 是快照读,走 MVCC;SELECT ... FOR UPDATE、UPDATE、DELETE 是当前读,读最新版本并加锁。InnoDB 在可重复读下通过间隙锁、临键锁减少当前读的幻读。
    • 以 InnoDB 和所用 MySQL 版本的官方文档为准。

    可能的追问: 可重复读下真的完全没有幻读吗、能举个例子吗?间隙锁会带来什么问题(死锁、并发下降)?

    练一练
  17. 17遇到一条慢 SQL,你会怎么优化?情景应变技术二面校招 · 社招深挖

    考察点: 数据库调优的方法论:发现、分析、优化、验证,以及是否真的动手做过。

    答题思路:

    • 发现:开启慢查询日志,或通过监控和链路追踪找到耗时高的接口和对应 SQL。
    • 分析:用 EXPLAIN 看执行计划——是不是全表扫描、用了哪个索引、预估扫描行数、有没有 Using filesort 或 Using temporary;必要时用 EXPLAIN ANALYZE 看实际执行情况。
    • 优化手段由浅到深:补索引或调整联合索引的列顺序;改写 SQL(避免在索引列上用函数、避免 SELECT *、用覆盖索引减少回表);深分页改成按上一页最后一条记录的 ID 往后查;大查询拆成小查询;冗余字段减少关联;数据量真的太大再考虑归档、读写分离、分库分表。
    • 验证:在相近数据量的环境里对比优化前后的执行计划和耗时;上线后看监控确认。
    • 注意:线上加索引要评估表大小和锁的影响,选择低峰期执行。

    示范回答(校招版):

    我会按「找到它、看懂它、改掉它、验证它」四步来。我在【课程项目 / 实习项目】里做过一次:订单列表页按用户和时间范围查询,数据造到【几十万】条之后,接口要【2 秒】左右。我先开了慢查询日志确认是这条 SQL,然后用 EXPLAIN 看,发现 type 是 ALL,也就是全表扫描,原因是表上只有主键索引。查询条件是 user_id 等于某值、create_time 在一个范围内,再按 create_time 倒序。我建了一个 (user_id, create_time) 的联合索引,把等值条件放在前面、范围条件放后面,这样既能过滤又能直接利用索引的顺序,不用再额外排序。改完再看执行计划,走了新索引,Extra 里的 Using filesort 也没了,接口耗时降到【几十毫秒】。另外我发现翻到很后面的页还是慢,又把分页改成了「带上上一页最后一条的时间和 ID 往后查」。这些数字是我本地造数据测的,我知道线上环境还要考虑更多因素。

    示范回答(社招版):

    我们在【某个运营后台的报表查询】上遇到过这个问题:大促前后数据量涨上来,这个接口的较慢分位耗时到了【数秒】,还拖慢了同库其他接口。排查分三步:先从慢日志和链路追踪定位到两条 SQL;然后看执行计划,第一条是多条件筛选,优化器选错了索引,选了一个区分度很低的状态字段的索引,扫描行数【几十万】;第二条是深分页,偏移量很大时要先扫过前面所有行再丢掉。对第一条,我们根据实际的查询条件组合重建了联合索引,把区分度高的条件放在前面,并去掉了一个已经被联合索引覆盖的冗余单列索引;对第二条,和产品沟通后把「跳到任意页」改成「上一页 / 下一页」,用游标方式往后查。加索引那张表有【千万级】数据,我们在低峰期用在线 DDL 执行,执行前评估了磁盘空间和主从延迟。上线后这个接口耗时降到【几百毫秒】以内。之后我们把慢查询纳入了每周巡检,新增 SQL 在评审时要求附上执行计划,这比事后救火成本低得多。

    可能的追问: 优化器为什么会选错索引、怎么处理?大表加字段或加索引怎么做才不影响线上?什么时候才需要分库分表?

    练一练
  18. 18缓存穿透、缓存击穿、缓存雪崩分别是什么?怎么解决?专业知识技术一面校招 · 社招基础

    考察点: 缓存使用的基本风险意识。

    答题思路:

    • 缓存穿透:查询一个根本不存在的数据,缓存和数据库都没有,每次请求都打到数据库,常见于恶意请求。解决:缓存空值并设较短过期时间;用布隆过滤器提前拦截肯定不存在的 key;接口层做参数校验。
    • 缓存击穿:某一个热点 key 过期的瞬间,大量请求同时打到数据库。解决:重建缓存时加互斥锁,只让一个请求去查库,其他请求等待或返回旧值;热点数据设置逻辑过期,后台异步刷新。
    • 缓存雪崩:大量 key 同一时间过期,或者缓存服务整体不可用,请求全部落到数据库。解决:过期时间加随机值打散;缓存做高可用部署;数据库前加限流和降级;本地缓存做多级兜底。
    • 一句话区分:穿透是「查不存在的」,击穿是「一个热点失效」,雪崩是「一大片失效」。

    可能的追问: 布隆过滤器的原理和误判是怎么回事?Redis 的过期删除和内存淘汰策略有哪些?

    练一练
  19. 19缓存和数据库的数据怎么保持一致?情景应变技术二面社招 · 校招深挖

    考察点: 是否理解一致性问题没有完美解,能否根据业务做取舍。

    答题思路:

    • 先表态:缓存和数据库是两个系统,强一致代价很高,大多数场景追求的是最终一致,并把不一致的时间窗口控制在业务可接受的范围内。
    • 常用方案:先更新数据库,再删除缓存(而不是更新缓存)。删除而不是更新,是因为并发更新缓存容易乱序,而且很多缓存值是计算出来的,删掉等下次读时再加载更省事。
    • 为什么不先删缓存再更新数据库:删完缓存、数据库还没更新时,另一个读请求会把旧值重新写回缓存。
    • 进一步加固:删除缓存失败时重试(可以借助消息队列);延迟双删(更新数据库后延迟一小段时间再删一次);订阅数据库变更日志,由独立的程序负责删除缓存,业务代码不用关心。
    • 兜底:缓存一定要设置过期时间,即使出现不一致,也会在过期后自愈。
    • 对一致性要求特别高的数据(比如余额),直接读数据库,不走缓存。

    可能的追问: 「先更新数据库再删缓存」在什么极端情况下仍然会不一致?延迟双删的延迟时间怎么定?

    练一练
  20. 20消息队列怎么保证消息不丢失、不重复消费?专业知识技术二面社招进阶

    考察点: 对消息链路的完整理解,以及幂等设计。

    答题思路:

    • 先把链路拆成三段:生产者发送、消息队列存储、消费者消费,每一段都可能丢消息。
    • 生产端:使用同步发送或带回调的异步发送,确认发送成功;失败要重试并记录。以 Kafka 为例,可以要求所有同步副本都写入后才确认,并开启生产者幂等。
    • 存储端:消息持久化,设置多副本,并配置最少同步副本数,避免只写了一个节点就确认。
    • 消费端:业务处理成功后再提交消费位点或确认,而不是一拿到消息就确认。
    • 不重复:由于有重试,至少一次投递几乎不可避免,所以重点是消费端做幂等。常见做法:用业务唯一键(如订单号)建唯一索引;处理前查一下是否处理过;状态机只允许按顺序流转;用去重表记录已处理的消息 ID。
    • 一句话:不丢靠「每一段都确认」,不重靠「消费端幂等」。

    可能的追问: 消息积压了怎么处理?怎么保证消息的顺序?什么是事务消息、解决什么问题?

    练一练
  21. 21设计一个短链接服务。案例分析技术二面校招 · 社招深挖

    考察点: 系统设计的思路:先澄清需求,再估算规模,再给出设计,最后讨论扩展和取舍。

    答题思路:

    • 澄清需求:功能上要支持长链转短链、短链跳转、是否支持自定义短码、是否有过期时间、是否需要访问统计;非功能上关注读多写少、跳转要快、短码不可预测(防止被遍历)。
    • 估算规模:和面试官对齐每天新增多少条、访问多少次,估算存储量和读写比例。数字用面试官给的或自己假设的,说清楚是假设。
    • 短码生成:方案一是全局唯一的自增 ID 转成 62 进制字符串,短且不重复,但容易被猜到,可以加一层混淆;方案二是对长链做哈希后取一部分,要处理冲突。ID 生成可以用数据库号段或雪花算法这类分布式 ID 方案。
    • 存储:短码到长链的映射,短码作为主键或唯一索引;同一个长链是否复用短码要提前定下来。
    • 读路径:跳转请求先查缓存,未命中再查数据库并回填;热点短链可以加本地缓存。
    • 跳转方式:301 永久重定向浏览器会缓存,减轻服务压力,但统计不到后续访问;302 临时重定向每次都会请求服务,方便统计。按是否需要统计来选。
    • 统计:访问记录异步写入消息队列,再批量落库或进入分析系统,不阻塞跳转。
    • 扩展:数据量大了按短码分库分表;防刷要做限流和恶意链接检测。

    校招怎么答 / 社招怎么答: 校招把需求澄清、短码生成、存储和缓存讲清楚,有条理即可;社招要主动讨论容量估算、高可用、热点处理、数据迁移和监控,并说明每个取舍的依据。

    可能的追问: 雪花算法的结构是什么、时钟回拨怎么办?如果要求同一个长链永远只生成一个短链,怎么设计?

    练一练
  22. 22分布式锁有哪些实现方式?各有什么坑?专业知识技术二面社招深挖

    考察点: 分布式场景下的并发控制,以及对边界情况的考虑。

    答题思路:

    • 为什么需要:多个服务实例之间,单机锁管不住,比如防止定时任务重复执行、防止库存超卖。
    • 数据库实现:用唯一索引插入一条记录表示加锁,删除表示解锁;简单但性能一般,要处理锁不释放的问题。
    • Redis 实现:用「不存在才设置」并带过期时间的命令一步完成加锁;value 存一个唯一标识,解锁时先比较再删除,并且这两步要用脚本保证原子性,避免删掉别人的锁。
    • 坑一:锁过期了业务还没执行完,别人拿到了锁。解决:后台线程定时续期(看门狗机制)。
    • 坑二:主从切换时,锁还没同步到从节点就切换了,导致锁丢失。对一致性要求极高时可以考虑基于共识协议的协调服务(如 ZooKeeper、etcd)实现的锁。
    • 协调服务实现:利用临时顺序节点,客户端断开后节点自动删除,天然避免死锁;可靠性高,但性能比 Redis 低。
    • 更稳妥的设计:锁只是第一道防线,关键写操作再配合版本号或「围栏令牌」做校验,防止过期的持锁者把数据写坏。

    可能的追问: 可重入的分布式锁怎么实现?不用分布式锁,防超卖还有什么办法(数据库乐观锁、预扣库存)?

    练一练
  23. 23讲一个你项目里遇到的最难的技术问题,你是怎么解决的?行为题(STAR)技术二面业务面校招 · 社招 · 实习 · 跳槽转行深挖

    考察点: 真实参与度、技术深度、解决问题的思路。几乎必问,后面的追问往往决定这一轮的结果。

    答题思路:

    • 用 STAR 结构:背景(项目是什么、问题是什么、为什么难)→ 任务(你负责什么)→ 行动(排查和方案,重点讲你考虑过的几种方案和取舍)→ 结果(可量化的结果,用你自己的真实数据)。
    • 「难」要具体:并发导致的数据错误、性能瓶颈、线上偶现的故障、老系统改造、跨团队依赖,挑一个讲透,而不是罗列一堆。
    • 主动讲取舍:当时为什么没选另一个方案。
    • 准备好被追问三层:「为什么这么做」「有没有更好的办法」「如果重来会怎么改」。
    • 不要把团队的成果说成自己的,面试官追问两层就能听出来。

    示范回答(校招版):

    我讲一个我在【课程项目 / 实习项目:某个选课 / 抢购类系统】里遇到的问题。背景是这个功能在开放的那一刻会有很多人同时提交,我负责后端的下单接口。压测时我发现,【库存为 100】的商品最后卖出了【一百多】件,出现了超卖。我先在本地复现,确认问题出在「先查库存、再扣库存」这两步之间,多个请求同时查到了库存充足。我考虑了三个方案:一是在 Java 代码里加 synchronized,但服务部署多个实例就管不住了;二是用分布式锁,但所有请求排队,吞吐量会很低;三是把扣库存改成一条带条件的 SQL,只有库存大于零才扣减,靠数据库行锁保证原子性。我选了第三种,因为它最简单,而且这个场景的并发量数据库扛得住。改完再压测,没有再出现超卖。之后我又发现同一个用户快速点两次会生成两个订单,就加了「用户 ID + 商品 ID」的唯一索引做幂等。这件事让我明白,并发问题要先在本地稳定复现,再选能解决问题的最简单方案。

    示范回答(社招版):

    我讲【某核心业务系统】的一次稳定性问题。背景是这个服务每天有几次接口超时突增,持续【几十秒】就自己恢复,监控上看不出明显规律,已经影响到上游的成功率。我是这个服务的主要负责人之一,牵头排查。第一步是收集证据:把超时时间点和 GC 日志、数据库慢日志、下游调用耗时对齐,发现每次超时都伴随一次较长的 GC 停顿,而停顿之前老年代上涨很快。第二步定位:在一次停顿前后导出堆转储,发现大量对象来自一个按天汇总的本地缓存,它在某个定时任务刷新时会整体重建,新旧两份数据同时存在,瞬间占用翻倍。第三步方案:我们对比了三种做法——调大堆、改成增量刷新、把这份数据挪到分布式缓存。调大堆只是推迟问题;挪到分布式缓存会让每次请求多一次网络调用;最后选了增量刷新,并给本地缓存加上容量上限和监控。同时把定时任务从整点改成错峰执行。上线后这类超时在【观察周期】内没有再出现,接口较慢分位耗时也从【X 毫秒】降到【Y 毫秒】。复盘时我们补了两条规则:本地缓存必须设上限并接入监控;涉及大批量数据重建的任务要做内存评估。这件事让我更相信,偶发问题要先把多个维度的时间线对齐,证据会自己说话。

    可能的追问: 如果当时数据量再大十倍,你的方案还成立吗?这个问题本来可以更早发现吗?你在里面具体写了哪部分代码?

    练一练
  24. 24需求很急,但你觉得技术方案有隐患,你会怎么办?行为题(STAR)业务面终面社招 · 跳槽转行进阶

    考察点: 风险意识、沟通方式、能否在业务压力下做出负责任的取舍。

    答题思路:

    • 先把隐患说清楚、量化:不是说「我觉得不安全」,而是说「这样做在【某种情况】下会导致【数据重复 / 资损 / 服务不可用】,概率和影响大概是多少」。
    • 给替代方案而不是只说不行:比如「先上一个简化版本满足上线,同时加上开关和监控,下个迭代补完整方案」,或者「这个功能先在小范围灰度」。
    • 和需求方、上级对齐优先级:把选项和各自的风险摆出来,由有决策权的人拍板,自己负责把风险讲透。
    • 留下记录:决策结论、已知风险、后续补救计划写进文档或任务单,避免以后说不清。
    • 讲一个真实的例子,最后说结果和反思。避免两种极端:一味顺从不提风险,或者坚持己见拖延上线。

    校招怎么答 / 社招怎么答: 校招可以讲实习或团队项目中赶截止日期时的类似经历,重点体现你会主动提出问题;社招要讲出完整的风险评估和推动过程,以及事后的机制改进,比如把类似检查加进了方案评审清单。

    可能的追问: 如果最后决策者还是坚持按原方案上线,出了问题怎么办?你有没有过判断错误、其实隐患没那么大的时候?

    练一练
  25. 25你之前做的不是 Java 后端(或者不是计算机专业),为什么想转过来?你是怎么准备的?动机与求职意向HR面业务面跳槽转行 · 校招进阶

    考察点: 转行动机是否真实、稳定,学习能力和已经具备的实际能力。

    答题思路:

    • 动机要具体、正向:不要说「后端工资高」「原来的工作没前途」,而是说出你接触后端的契机,以及你在其中获得的兴趣和成就感,比如在原工作中写脚本提升了效率,或者参与过系统对接。
    • 用事实证明能力:讲你系统学了什么(Java 基础、Spring、MySQL、Redis),做了什么完整项目(从需求到部署上线),代码放在哪里可以看。
    • 把原背景变成优势:原来做测试的懂质量保障,做运维的懂部署和监控,做业务的懂需求,做前端的懂接口协作。
    • 对差距要坦诚:承认在大规模系统经验上的不足,并说明你的补足计划。
    • 不要编造工作经历或夸大项目规模,技术面一追问就会露馅。

    校招怎么答 / 社招怎么答: 非科班校招生重点讲自学路径和项目,说明你已经补齐了数据结构、网络、数据库等基础;社招转行者重点讲原岗位经验如何迁移,以及你做出的可以运行、可以展示的项目。

    可能的追问: 你的项目部署在哪里、遇到过什么问题?如果入职后发现后端工作很枯燥怎么办?你给自己定的一年目标是什么?

    练一练
  26. 26面试最后,你有什么想问我们的吗?反问技术二面业务面HR面校招 · 社招 · 实习 · 跳槽转行基础

    考察点: 你对这份工作的关注点、思考深度,以及真诚的兴趣。

    答题思路:

    • 不要说「没有问题」,也不要一上来就问加班和福利(可以留到 HR 面或拿到意向后再问)。
    • 技术面可以问:团队负责的系统大致是做什么的、目前最大的技术挑战是什么、技术栈和研发流程是怎样的、线上问题怎么分工处理。
    • 主管面可以问:这个岗位最希望新人在前几个月解决什么问题、团队里表现好的人有什么共同特点、新人怎么上手。
    • HR 面可以问:后续流程和时间节点、培训和转正安排。
    • 问题最好和面试中聊到的内容有关联,显得你在认真听。

    可能的追问: 面试官可能顺着你的问题反问你:「如果让你来解决这个挑战,你会怎么做?」所以问之前自己先想一想。

    练一练

点「练一练」会复制这道题,并跳到页面底部的下载入口;打开 OfferGod 模拟面试后粘贴即可。

05校招、社招和转行准备重点有什么不同?

维度校招 / 实习社招跳槽转行
基础知识占比高,系统地问 Java 基础、集合、并发、JVM、数据库、网络占比下降,但答不上来会直接扣分一样会系统地问,是证明「补齐了基础」的关键
算法与手写笔试和一面常有编程题,简单到中等难度视公司而定,多为中等以下,或结合场景的代码题按校招标准准备,至少常见类型都练过
框架会用 Spring Boot,能讲清 IoC、AOP、事务的基本原理原理 + 踩过的坑 + 在项目里的最佳实践会用并理解基本原理,能说清自己项目里怎么用的
项目课程、比赛、实习、个人项目,看亲手写的深度业务背景、你的角色、方案对比、量化结果、线上问题至少一个从需求到部署的完整项目,能讲清每个技术选择
系统设计可能出简单的设计题,看思路是否清晰中高级岗位的重点,要讲容量、高可用、扩展和取舍能讲清自己项目的架构,对常见设计题有基本思路
线上与稳定性知道常见问题的排查思路必须有真实案例:怎么发现、怎么止血、怎么定位、怎么复盘可以讲本地或自己部署环境中的排查经历
软技能学习能力、沟通、对后端的兴趣跨团队协作、推动落地、带新人、业务理解转行动机、学习速度、原有经验的迁移
常见减分点只背八股不会写代码、项目说不出细节只讲「做了什么」不讲「为什么」、没有可量化结果项目照着教程做、讲不出自己的思考,或夸大经历

06准备清单(可打印)

投递前

  • 拆一遍目标岗位的 JD,按上面的表格列出要重点准备的知识点
  • 简历上每一个技术名词都确认自己能被追问三层,不熟的删掉
  • 项目经历用「背景—职责—行动—结果」写,结果尽量用自己的真实数据
  • 准备好可展示的代码仓库(确认能打开、README 写清楚怎么运行)
  • 社招:梳理近两三年 2–3 个代表性项目和 1–2 次线上问题处理,各写一页要点
  • 转行:准备一个从需求、设计、开发到部署的完整项目,并能讲出每个技术选择的原因

面试前一周

  • Java 基础与集合过一遍:HashMap、ConcurrentHashMap、String、equals 与 hashCode
  • 并发过一遍:锁、volatile、线程池参数和执行流程、AQS 基本思路
  • JVM 过一遍:内存区域、垃圾回收器、OOM 和 Full GC 排查步骤
  • Spring 过一遍:IoC、AOP、Bean 生命周期、事务失效场景、自动配置
  • MySQL 过一遍:索引结构与失效、EXPLAIN、隔离级别与 MVCC、锁
  • 缓存与消息过一遍:穿透击穿雪崩、缓存一致性、消息不丢不重
  • 算法按类型练:数组字符串、哈希、双指针、链表、树、简单动态规划
  • 至少完整练一道系统设计题,按「需求—估算—设计—扩展」说出来
  • 准备项目深挖:每个项目写出「最难的点、方案对比、如果重来会怎么改」
  • 准备 3–4 个行为题故事:最难的问题、线上故障、协作分歧、主动推动的事

面试前一天

  • 远程面试:检查网络、摄像头、麦克风、共享屏幕和在线编辑器能否正常使用
  • 准备一份 1–2 分钟的自我介绍,突出技术栈和代表项目
  • 把简历放在手边,再读一遍自己写的项目和项目里的关键数据
  • 在纸上画一遍核心项目的架构图,确认能边画边讲
  • 准备 2–3 个反问问题
  • 早点休息

面试后

  • 当天写复盘:被问到了哪些题、哪些没答好、追问停在了哪一层
  • 把没答好的题补上,整理进自己的题库
  • 社招:记录每家公司的流程和反馈节奏,方便安排后续面试
  • 一周左右没消息可以礼貌询问进度

07常见误区有哪些?

  • 八股背得滚瓜烂熟,代码写不出来。

    能讲清 HashMap 的扩容过程,却写不出一个线程安全的单例,面试官会觉得基础不实。每个知识点都配一段自己写过、跑过的代码。

  • 项目只讲用了什么技术,不讲为什么。

    「我用了 Redis 和 Kafka」不是亮点,「当时查询压力集中在少量热点数据上,所以加了缓存;下单后的通知不需要同步完成,所以用消息队列异步处理,并在消费端做了幂等」才是。

  • 简历写了「熟悉高并发、分布式」,却讲不出一个真实场景。

    写在简历上的每个词都可能被深挖,没做过就如实写你做过的,比被追问到答不上来好得多。

  • 结果没有数据,或者数据编得太夸张。

    优化类经历要有前后对比,但数据要真实、能解释,能说出是在什么环境、用什么方法测的。

  • 线上问题只讲「重启了就好了」。

    面试官想听的是你怎么保留现场、怎么定位根因、怎么避免再次发生。

  • 系统设计题一上来就画架构图。

    先问清需求和规模,再动手设计,边设计边说明取舍,比直接堆一堆组件名更能体现水平。

  • 遇到不会的题硬编。

    坦诚说「这块我了解不深,我的理解是……」,再说你会怎么去查证,比编一个错误答案好得多。

  • 转行同学照着教程做一个项目就写上简历。

    至少要在教程基础上做出自己的改动,比如加一个新功能、解决一个教程没处理的问题,并能讲清楚为什么这么改。

  • 反问环节说「没有问题」。

    准备两三个真诚的问题,比如团队目前最大的技术挑战是什么,能体现你的兴趣和思考。

08你被问到过类似的题吗?

你在 Java 后端面试里遇到过这页没收录的题吗?或者被某道题的追问问住过吗?欢迎通过页面底部的「发现内容有误或侵权?告诉我们」入口,把题目和当时的情况发给我们,采纳后会补进题库,帮到后面准备面试的人。

09参考来源与审稿

发现内容有误或侵权?告诉我们,3 个工作日内处理

看完想开口练一练?

OfferGod 电脑端可以按岗位和轮次做模拟面试,练完看复盘报告。