
金三银四又来了。每年这个时候后台私信里堆满了“大厂Java面试题”的求问很多人复习时东翻一篇西找一段知识点散得像一地芝麻真上了面试场一问一个卡壳。这篇文章就是帮你把这一地芝麻收拾成串——我把过去几年在一线面试别人、也被别人面的过程中反复出现的Java题目整理成一份带答案解析的汇总覆盖基础语法、集合源码、并发编程、JVM调优、Spring原理、场景设计这些大厂必考方向。不管你是刚准备春招的应届生还是打算跳槽的两年经验开发这份清单都能用来做系统自查哪些题你能不看答案就答全哪些题你心里其实没底一测便知。顺便说一句这些题目不是从网上随手抄的而是结合了我自己出题的习惯和同行交流时的高频题库答案解析也尽量还原了面试官追问时的真实语境。建议你先自己答一遍再对答案最后重点琢磨“为什么这么答”和“哪里最容易被追问”。1. 整体设计与复习思路拆解1.1 大厂面试题的核心考察逻辑先说一个很多人没想明白的事大厂面试官不是考你背了多少题而是通过题目判断你的技术上限和下限在哪里。下限是你作为工程师能不能把日常工作干明白比如集合用不对、线程池参数乱填、SQL写出来跑不动这些都是硬伤上限是你面对未知问题有没有推演能力比如让你设计一个高并发下单系统你怎么拆解幂等、库存、防超卖这些环节。所以我整理的这份题目清单刻意分成了“基础题”和“场景题”两大类。基础题大多是八股文考察记忆和理解比如HashMap的原理、JVM内存分区场景题则是让你写伪代码、画流程、聊取舍比如“如何保证多线程下单时的数据一致性”。复习时千万不要只背基础题那只能过第一轮电话面到了现场面写代码和聊项目场景题才是生死关。1.2 不同经验段的复习侧重点应届生和实习生面试官重点看基础牢不牢Java语法、集合、JVM、网络编程这些是重头编程题也偏简单比如手写冒泡排序、判断字符串中的字符类型。1到3年经验的开发重点开始转向并发编程、Spring原理、MySQL索引和事务隔离级别编程题会出现“LRU缓存实现”“两个线程交替打印”这类。3年以上的高级岗除了原理还会追问设计方案比如“你们的分布式事务怎么做”“线上OOM怎么排查”这时候光背题没用必须有真实踩坑经历支撑。不同阶段的人看这份文章建议按自己的目标岗位跳跃式阅读不用从头啃到尾。但有一类题是所有人都躲不开的那就是集合和并发接下来这两块我会展开讲透。2. 核心细节解析与高频考点2.1 Java基础类必考题目题目一String、StringBuilder、StringBuffer的区别这是面试官热身最爱问的题没有之一。三者的核心区别就两个维度可变性和线程安全。String是不可变的每次拼接都会创建新对象循环里做字符串拼接会浪费大量内存实际开发中偶尔用加号拼接没问题但大量拼接一定要用StringBuilder。StringBuffer和StringBuilder的可变性一样区别在于StringBuffer的方法加了synchronized线程安全但性能略低。回答的时候最好能补一句JVM层面的理解String不可变的设计保证了字符串常量池的复用也是HashMap用String做key时hash值稳定的前提。这句话一出来面试官就会觉得你不是在背书而是理解了设计意图。题目二和equals()有什么区别基础中的基础但很多两三年经验的程序员回答时还是含糊。-比较的是引用地址基本数据类型比较的是值-equals()是Object的方法默认行为等价于但String、Integer这些类重写了它变成比较内容。追问率最高的场景是Integer a 128; Integer b 128; a b是true还是false。答案是false——因为Integer缓存范围是-128到127超出这个范围每次都会new新对象。这里有个很容易被追问的细节Integer a 128和Integer a new Integer(128)行为不同前者走了valueOf的缓存判断后者必定新建对象。题目三接口和抽象类怎么选记住几个关键差异就好抽象类用extends一个类只能继承一个接口用implements可以多实现。抽象类可以有成员变量和构造方法接口的变量默认是public static final。JDK8之后接口可以有default和static方法但依然不能有实例字段。实际设计时我的习惯是强调“是什么”的关系用抽象类强调“能做什么”的能力用接口。比如定义一个动物抽象类猫狗继承它定义一个飞行能力接口飞机和鸟都能实现它。面试时如果能主动说出这个设计准则比单纯背区别加分很多。2.2 集合框架源码级追问题目四HashMap的底层实现和put流程这道题几乎是大厂Java面试的必考题问法多样但内核一致。回答思路按版本分JDK7是数组链表JDK8是数组链表红黑树。put流程可以概括为四步先对key的hashCode做扰动计算然后按(n - 1) hash定位到数组槽位如果槽位为空直接放入节点不为空则遍历链表比较key是否相同相同则覆盖value如果链表长度达到8且数组长度达到64链表转红黑树。追问几个高频点为什么阈值是8因为泊松分布下链表长度达到8的概率极低约千万分之一这个阈值兼顾了查询性能和转换开销。为什么用红黑树不用平衡二叉树红黑树虽然牺牲了严格的平衡性但减少了旋转次数插入删除综合性能更优。为什么负载因子是0.75时间和空间成本的折中太高了冲突变多太低了浪费空间。题目五ArrayList和LinkedList的区别这题看似简单但高手和新手的答案差别巨大。新手说“一个数组一个链表一个查询快一个增删快”这个答案对但只值一半分。更好的回答是ArrayList基于动态数组默认容量10扩容时按1.5倍增长并通过Arrays.copyOf迁移数据LinkedList基于双向链表除了List接口还实现了Deque可以当队列和栈用。还要补一句实际开发中LinkedList的“增删快”是有条件的只有在头尾操作时成立如果是按索引插入LinkedList要先遍历到那个位置复杂度O(n)反而可能比ArrayList更慢。这里我建议面试时主动引申一下ArrayList的subList()返回的是内部视图修改它会直接影响原列表而且原列表结构被修改后子列表会快速失败抛出ConcurrentModificationException。这种细节说出来不仅能体现源码阅读深度还能自然引出fail-fast机制的话题。3. 并发编程、JVM与框架实操过程3.1 并发编程核心题的完整推演题目六synchronized和ReentrantLock的区别问到并发这是绕不开的第一题。参考答案分四点synchronized是JVM层面的关键字ReentrantLock是JDK提供的APIsynchronized自动释放锁ReentrantLock必须手动unlock一般在finally里释放ReentrantLock支持公平锁、可中断、可绑定多个Condition条件队列synchronized都没有JDK6之后synchronized引入了锁升级机制无锁→偏向锁→轻量级锁→重量级锁性能差距缩小了很多。加分回答要落在“怎么选”上如果只是简单的互斥同步synchronized足够代码简洁还不容易忘释放锁如果需要超时等待、公平性保证、多个条件队列这些精细化控制再考虑ReentrantLock。面试官听你说出“推荐优先用synchronized除非有明确需求”这句话会觉得你是有实际项目经验的人而不是只会背对比表格。题目七线程池的核心参数和执行流程线程池是大厂项目常客也是面试必考。七个参数要背熟corePoolSize核心线程数、maximumPoolSize最大线程数、keepAliveTime空闲线程存活时间、unit时间单位、workQueue任务队列、threadFactory线程工厂、handler拒绝策略。执行流程用四句话概括先跑核心线程满了放进队列队列满了创建临时线程线程数达到最大值再触发拒绝策略。追问热点是拒绝策略内置四种AbortPolicy直接抛异常、CallerRunsPolicy由调用线程执行任务、DiscardPolicy静默丢弃、DiscardOldestPolicy丢弃最老任务。实际项目中我见过最多的是自定义策略比如把任务持久化到数据库或消息队列等高峰期过去再异步重放这是面试官爱听的实战方案。题目八ThreadLocal的原理和内存泄漏问题ThreadLocal每次被问都是双刃剑答好了显得你懂底层还懂坑答不好就暴露了知识盲区。原理层面要讲清楚每个Thread内部维护一个ThreadLocalMapkey是ThreadLocal对象本身弱引用value是set进去的值。所以ThreadLocal的数据其实是线程私有的不存在并发竞争问题。内存泄漏是必追问项ThreadLocalMap的key是弱引用但value是强引用。如果ThreadLocal对象被回收key变成nullvalue却还被Entry强引用着如果线程长期存活比如线程池里的核心线程这条Entry就永远无法回收造成泄漏。解决办法是每次用完调用remove()这也是我日常开发里的强制规范。3.2 JVM内存与调优实操细节题目九JVM内存区域划分哪些区域会OOM这道题是JVM部分的敲门砖。按Java8以后的版本回答堆内存存放对象实例是GC主要区域OOM最常发生虚拟机栈每个线程一个栈帧存局部变量表、操作数栈方法递归太深会抛StackOverflowError方法区Java8的元空间存类元信息、常量、静态变量加载类太多也会OOM程序计数器是唯一不会OOM的区域。本地方法栈给native方法用平时聊得少但别漏掉。回答时最好加一个实例说明线上服务报java.lang.OutOfMemoryError: Java heap space先dump堆快照用MAT分析是对象太多了还是对象太大再定位到具体的业务代码。这样一套流程讲下来面试官对你的工程能力认可度会高很多。题目十垃圾回收算法和常见收集器GC部分要掌握三个基础算法和一个分代假设。复制算法适合新生代因为存活对象少复制成本低但浪费一半空间标记清除会产生内存碎片标记整理适合老年代没有碎片但移动对象有开销。分代收集就是把堆分成新生代和老年代新生代用复制算法Survivor区老年代用标记整理兼顾吞吐和延迟。收集器重点说G1它把堆分成多个Region维护一个优先列表跟踪每个Region的垃圾回收价值回收时优先处理垃圾最多的Region实现可预测的停顿时间。现在线上很多服务已经在用ZGC它的核心是染色指针和读屏障能把停顿时间压到10毫秒以内。这两个我记得住关键特性就够了但面试时要能说清楚自己项目的实际使用情况。3.3 Spring框架与业务场景落地题目十一Spring Bean的生命周期在Spring框架的面试题里Bean生命周期属于必背内容。完整流程可以概括成实例化→属性填充→Aware回调→BeanPostProcessor前置处理→初始化方法InitializingBean或init-method→BeanPostProcessor后置处理→使用→销毁DisposableBean或destroy-method。面试时展示深度的方式是主动提到BeanPostProcessor的应用场景Spring AOP就是通过它在Bean初始化后创建代理对象Autowired的注入也是通过AutowiredAnnotationBeanPostProcessor完成的。这套机制理解了后面聊循环依赖就顺了。题目十二Spring的事务传播行为事务失效的场景事务传播行为有七种核心记三个就够了。REQUIRED默认传播如果当前没有事务就新建一个有就加入当前事务REQUIRES_NEW不管有没有都新建事务把原来的挂起NESTED嵌套事务利用保存点实现局部回滚。实际开发中用NESTED的场景不少比如批量导入一条数据失败不影响其他数据入库。事务失效的经典场景必须背熟方法被final修饰Spring通过CGLIB生成子类代理final方法无法被重写方法内部通过this调用另一个带Transactional的方法绕过了代理对象方法不是public的异常被try-catch吞掉数据库引擎不支持事务比如MyISAM。我实际踩过的坑是try-catch吞异常线上数据对不上查了半天才发现业务代码里把异常捕获后打了日志Spring根本感知不到所以事务回滚压根没触发。题目十三MyBatis-Plus如何根据实体类自动生成建表SQL这道题在热词里出现了确实是个很实用的功能面试或工作中聊到代码生成器时经常带上它。MyBatis-Plus本身没有直接提供“实体类转建表语句”的开箱工具但常见的实现思路是结合MyBatis-Plus Generator的数据库逆向工程反过来利用TableInfoHelper解析实体类上的TableName、TableField注解拼出CREATE TABLE语句。一个更轻量的做法是在项目启动时做表结构校验写一个Configuration类扫描指定包下的实体类遍历每个类的字段比较数据库中实际的表字段缺少的字段用ALTER TABLE自动补上。这个方案适合小团队快速迭代的场景能减少人工维护SQL脚本的工作量。需要注意的点是字段类型映射要单独处理比如LocalDateTime映射到datetimeBigDecimal映射到decimal(10,2)这部分必须根据业务精度需求配置成可调节的映射表。4. 高频场景设计题与编程题实操指南4.1 数据一致性与幂等设计题目十四如何保证多线程场景下的数据一致性这题在热词里出现了也是面试场景题的高频母题。回答要先问清楚业务场景因为不同场景方案差异很大。如果是单机多线程更新共享变量可以用AtomicInteger这类CAS工具或者加锁如果是分布式环境下多个服务操作同一份数据就要考虑分布式锁Redis的SETNX或ZooKeeper临时节点配合数据库乐观锁。比较完善的回答结构是先分析场景的并发冲突点再选方案最后说明极端情况下的兜底策略。题目十五接口的幂等性怎么设计幂等性是我面试高级工程师必问的题因为它在实际业务里太重要了。核心思路概括为让同一个请求执行多次和执行一次效果相同。常见做法有三种数据库唯一索引最简单可靠插入类业务常用Redis setnx做分布式锁标记适合防重复提交需要注意过期时间状态机校验适合订单类业务比如订单状态从“待支付”改成“已支付”只能有一次。加分回答要谈“先查再写”的并发漏洞两个请求同时查到订单是“待支付”都执行了更新状态机就乱了。解决方法是把判断条件放进SQL的WHERE子句里比如UPDATE orders SET status已支付 WHERE id? AND status待支付影响行数为0说明已经被处理过这种原子操作比应用层判断可靠得多。4.2 Controller层防爬虫实战思路题目十六Controller层如何防护爬虫这道题在热搜词里出现确实是现在后端开发的刚需。面试时能系统回答的人不多答好了很加分。我总结的防御思路按成本从低到高排列第一层校验请求头里的User-Agent和Referer过滤常见的爬虫标识这一层最基础但能挡住大量低端爬虫第二层在网关或拦截器里做IP维度的频率限制比如单IP每秒最多5次请求超过了直接返回429用Redis的INCR加过期时间实现成本很低第三层对敏感接口增加签名校验把参数按规则拼接后加盐做MD5服务端校验签名这能防住恶意构造请求的脚本第四层行为分析比如鼠标轨迹、请求间隔、页面停留时长这些参数异常的就弹验证码。面试时最好讲一个我实际用过的方案登录后的核心接口把用户token和IP绑定同时限制同一token的并发数用Redis的incr统计每秒请求量超过阈值就熔断一段时间。这套方案不需要引入太重的风控系统工程上可落地比空谈“我们上了验证码”有说服力。4.3 手写编程题常见类型题目十七冒泡排序手写与优化编程题最基础的一档但手写时能写出优化版本的人不多。基本版代码很简单public static void bubbleSort(int[] arr) { for (int i 0; i arr.length - 1; i) { for (int j 0; j arr.length - 1 - i; j) { if (arr[j] arr[j 1]) { int tmp arr[j]; arr[j] arr[j 1]; arr[j 1] tmp; } } } }优化点有两个如果某一轮循环中没有发生任何交换说明数组已经有序可以直接break记录最后一次交换的位置这个位置之后的元素已经有序下一轮的遍历范围可以缩小。能写出第二种优化的人说明真的理解算法本质而不是背代码。题目十八判断字符串中是否含有不是字母和数字的字符这道题对应热搜词中的“java 判断字符串中是否不是字母和数字”看起来简单其实考查的是对正则和字符编码的熟悉度。推荐答案是用String.matches配合正则public static boolean hasSpecialChar(String str) { return str.matches(.*[^a-zA-Z0-9].*); }如果面试官要求不许用正则那就用Character类的静态方法public static boolean hasSpecialChar(String str) { for (char c : str.toCharArray()) { if (!Character.isLetterOrDigit(c)) { return true; } } return false; }注意Character.isLetterOrDigit包含中文因为中文汉字是Unicode里的字母类如果业务上有特殊要求得用[a-zA-Z0-9]的范围判断来替代。题目十九递归求数字的某类题目以蓝桥杯风格为例热词里出现“java 蓝桥杯 数字题目”这里举一道典型的模拟题求一个整数各位数字之和直到结果为一位数。比如给定123451234515再156输出6。这题可以递归也可以迭代public static int digitSum(int num) { if (num 10) { return num; } int sum 0; while (num 0) { sum num % 10; num / 10; } return digitSum(sum); }蓝桥杯这类竞赛题的特点是边界条件多、数据规模大所以除了代码正确性还要注意用int还是long以及对0和负数的处理。这题还有个数学捷径对非0整数最终结果等于num % 9余数为0时答案是9——但面试时建议先写常规解法再说出这个优化显得你数学功底扎实。5. 常见问题与避坑经验分享5.1 面试官最爱挖坑的追问点很多候选人背题背得很熟但架不住追问。我这里把最容易踩坑的追问点列成速查表方便你们自查原题追问易错点HashMap原理为什么容量必须是2的幂因为(n-1)hash取模的前提是n为2的幂这样分布均匀且效率高ConcurrentHashMap原理JDK8还分段锁吗不再分段改用CASsynchronized锁单个Nodevolatile的作用能保证原子性吗只保证可见性和有序性不保证原子性i仍然线程不安全Spring Boot自动配置原理条件注解有哪些ConditionalOnClass、ConditionalOnProperty等常见几个要能说出场景MySQL索引失效最左前缀原则失效条件对索引列做函数运算、隐式类型转换都会导致失效关于volatile再补充一句它修饰引用类型和数组时有个常见误区volatile数组变量只能保证数组引用本身的可见性数组元素的修改依然是线程不安全的。这点我在面试时问过很多人能答对的极少。5.2 我亲身踩过的Java开发/面试坑面试别人这几年我发现两类候选人最常见的问题第一类是项目经验丰富但表达没条理问了三个问题全程没有一句“首先、其次、最后”听的人一头雾水第二类是基础扎实但项目细节说不清问他ORM的SQL执行流程、缓存和DB的一致性怎么做支支吾吾。对应的建议很简单面试前把每个项目的核心链路用“需求→方案→结果”三段式整理成文字稿反复练到能不看稿子讲清楚技术深度方面重点把集合源码、并发工具、Spring Bean生命周期这三块吃透这三块是连锁考点任何一个答好都能引出更多加分点。另外纸上手写代码一定要提前练——很多人IDE里写代码飞快白板上写就各种低级错误日常可以刻意练习在记事本里写代码不依赖编译器的自动补全。5.3 Java环境与工具链常见障碍面试或工作中还会碰到环境层面的问题虽然不算面试题但热词里出现了“java环境变量配置详细教程”“java启动失败怎么解决”我也简单收个尾。环境变量配置的核心就三个变量JAVA_HOME指向JDK安装目录PATH加%JAVA_HOME%\binCLASSPATH一般留空不配JDK9以后很多场景不需要。多JDK切换时只要改JAVA_HOME并把PATH里的顺序调整好就行Windows下记得新开命令行窗口再验证。启动失败最常见的几个原因端口被占用java.net.BindException用netstat -ano查PID再kill、堆内存不足调整-Xms和-Xmx参数、依赖冲突Maven里两个版本的jar包冲突用mvn dependency:tree排查。排查思路是先看日志定位异常类型再去查对应的常见原因不要瞎猜。这个问题在面试的“项目部署”环节也容易被顺带问到答得利索是加分项。最后分享一点个人感受面试本质是“技术交流”而不是“考试”心态上把它当成一次讨论反而更容易发挥出真实水平。这份题目汇总不能保证你拿到所有offer但把这些题吃透至少能让你在大部分Java岗位上做到心里有底。祝你们金三银四都拿到满意的结果。