上周面了一个候选人,简历发着光:
985 硕、大厂实习、LeetCode 刷了 400 题。
出了一道「用两个栈实现一个队列」
他三分钟写完,边界条件全过,时间复杂度最优。
我没要他。
因为他写代码那 20 分钟,全程沉默。
我问他「如果队列元素是对象,你的 equals 逻辑怎么处理」
他愣了一下说「没想过」。我故意改了题目条件——把栈换成优先队列——他头也不抬,继续按栈写。
他走之后,我在「沟通表达」那一栏打了个 2 分。
他不知道,我的评分表上,一共有 5 个维度。
代码能力,只覆盖了其中一个的一部分。
前前后后面了 500 多个 Java 程序员,从 P5 到 P8 都面过。
今天把这 5 个维度摊开写
太多人把时间砸在了不该砸的地方

代码不是跑通就行
这个维度,面试官在你写前 5 行代码的时候就打完分了。
大部分候选人以为「代码写对了 = 满分」。
但实际上,写出正确结果只是及格线。
剩下 60% 的分,在你不注意的细节里丢了。
1. 变量命名随意
见过太多这样的代码:
List<String> l = new ArrayList<>();
int n = 0;
for (int i = 0; i < l.size(); i++) {
n += l.get(i).length();
}
逻辑没错。但 l 是什么?n 是什么?为什么不叫 wordList 和 totalLength?
如果这是你写在生产环境的代码,同事 review 时会怎么想?
面试官看到这种命名,会在心里默默扣掉「代码可读性」的分数。大厂的代码不是给你一个人看的。
2. 异常处理只写 try-catch 空块
try {
FileInputStream fis = new FileInputStream("config.properties");
// ...
} catch (FileNotFoundException e) {
}
看到 catch 里空空如也的那一刻,我基本确定这个候选人在生产环境写的代码质量堪忧。
这不是 LeetCode,这是要考虑「文件不存在时系统应该怎么表现」的真实问题。
加分写法:
try (FileInputStream fis = new FileInputStream("config.properties")) {
// ...
} catch (FileNotFoundException e) {
log.error("配置文件未找到,将使用默认配置", e);
// 降级逻辑
}
一个 try-with-resources + 明确的降级策略 + 日志记录——这一下就拉开了差距。
3. 集合操作不考虑线程安全
面试官问:「这个 HashMap 在并发场景下会有什么问题?」
如果你的回答只有「线程不安全」四个字,而没有展开说 ConcurrentHashMap、synchronizedMap
甚至提到 Java 8 的 ConcurrentHashMap 和 Java 7 的区别
那你只是「知道」,不是「理解」。
这个维度怎么准备?
StringBuilder。ArrayList 而不是 LinkedList,时间复杂度是什么,空间复杂度又是什么。把选择变成自觉,而不是「下意识」。沉默是最大的扣分项
这是我见过候选人被淘汰最多、也是最冤的维度。
很多程序员面试时的心态是:「我把题做出来就行,别的不重要。」
但面试官要招的不是一台代码生成器,是一个能一起工作的同事。
场景 1:不提问直接写
面试官:「用 Java 实现一个 LRU 缓存。」
候选人听完,沉默 10 秒,开始写:
public class LRUCache {
private Map<Integer, Integer> map;
// ...
}
他在用 HashMap 自己维护链表。写了 15 分钟,逻辑复杂,边界条件没处理好,超时了。
——但面试官原本期待的答案是:「用 LinkedHashMap 的 accessOrder 参数,5 行代码搞定。」
如果他一开始问一句:「缓存大小固定吗?需要支持并发吗?可以基于现有数据结构吗?」
他会在 3 分钟内拿到 LinkedHashMap 这个提示,而不是浪费 15 分钟重新发明轮子。
场景 2:发现自己错了,硬着头皮写
一位候选人写到一半,发现自己的双指针边界条件处理错了。
他没说,继续往下写。结果后面全歪了。
如果他停下来的那一刻说:「等一下,我边界条件好像有问题,我重新理一下。」
这反而是加分项。承认错误并快速修正,比死撑到底更让面试官欣赏。
面试官要的不是演讲能力,是:
这三步,每一步都在告诉面试官:这个人可以合作。
初级和高级的分水岭
这一关,直接决定你的薪资是 15K 还是 40K。
初级候选人(P5-P6 水平)被问到「设计一个秒杀系统」:
「用 Redis 缓存库存,用消息队列削峰,数据库做最终扣减。」
——听起来都对,但全是散点,没有结构。
高级候选人(P7 水平)的答案会包含:
「先从业务指标出发:我们的目标 QPS 是多少?假设 10 万 QPS,每个请求处理时间控制在 50ms 以内。 架构上,我会做三层过滤: 第一层 CDN + Nginx 限流,过滤掉 90% 无效流量; 第二层 Redis Lua 脚本做原子扣减,保证不会超卖; 第三层 RocketMQ 异步写 DB,用事务消息保证最终一致性。 还有一些魔鬼细节:热点数据的多级缓存策略、库存预热、兜底降级方案……」
差别在哪? 不在「知道什么技术」,而在结构化的思考方式。
题目 | 考察点 |
|---|---|
设计一个短链接系统 | 分布式 ID 生成、Base62 编码、301 vs 302、布隆过滤器 |
设计一个消息推送系统 | Netty 长连接、心跳机制、消息可靠性、在线/离线状态管理 |
设计一个分布式事务方案 | Seata AT/TCC/Saga 模式对比、最终一致性、补偿机制 |
JVM 线上调优 | GC 日志分析、堆 dump 分析、Arthas 使用经验、真实案例 |
关键不是背答案,是你的思考过程有没有结构。
面试官不指望你 30 分钟设计出淘宝
他想看的是:给你一个模糊的问题,你能不能拆成有层次的技术方案。
面试前 15 分钟的隐形考试
面试官问「你对我们产品有什么了解」,不是在寒暄,是在打分。
回答 A:
「你们是做电商的,我以前也做过电商,技术栈挺匹配的。」
——这句话等于没说话。面试官在心里打了 1 分。
回答 B:
「我了解到你们的核心业务是跨境电商,主要面向东南亚市场。技术上我看你们用了 Spring Cloud Alibaba 那套体系,Nacos 做注册中心,Sentinel 做限流。我看你们技术博客提到过大促期间 QPS 峰值能到 50 万——我之前在公司做过类似的高并发场景,用的方案是……」
我面试他时眼睛亮了。这个人不是来海投的,他是真的想来这个团队。
面试前必做三件事:
面试官在找「明年能用的人」
**你的 Java 简历上的技术栈只是入场券。面试官真正想判断的是:你明年这时候值不值涨薪 **
两位候选人都写「熟悉 Spring Boot、MyBatis、Redis、MySQL」。
候选人 A 说:
「我平时用这些技术做业务开发,增删改查为主。」
候选人 B 说:
「最近在看 Spring Boot 3.x 的虚拟线程(Virtual Threads)支持,Java 21 的这个特性可能会改变我们写高并发代码的方式。我还对比了虚拟线程和 WebFlux 的适用场景,在 IO 密集型任务上虚拟线程更友好一些,CPU 密集型还是得用传统线程池……」
你面谁?答案不言自明。

常见问题:
低级回答:「我用过 var、record、switch 表达式。」(背特性列表)
高级回答:「我们项目最近从 Java 8 升级到了 Java 17,我用 sealed class 重构了原来用枚举+switch 的状态机,编译期就能检查分支完整性,少出了好几个线上 Bug。另外一个收获是 G1GC 在 Java 17 里的改进——」
区别在哪?不是「我会」,而是「我用了,而且思考了为什么用,带来了什么收益。」
面了 500 多人,我发现一个规律:被淘汰的人里,90% 不是技术不行,是方向不对。
他们把 90% 的时间砸在「算法题」这一个维度上,剩下 4 个维度完全裸考。
然后问:「为什么我刷了这么多题还是过不了?」
因为面试不是算法竞赛。
面试是——对方在找一个明年能扛事、能沟通、能成长的队友,不是一台答题机。
互动话题:你面试时在哪个维度踩过坑?评论区聊聊。