Java大厂面试现场:谢飞机硬刚面试官,从HashMap到DDD全程高能
场景:某互联网大厂会议室,面试官李老师面无表情翻着简历,对面坐着笑容灿烂的谢飞机。
第一轮:基础稳扎稳打?
面试官李老师:说说 HashMap 的底层结构?
谢飞机:嗯……数组 + 链表!JDK8 还加了红黑树,防止链表太长影响性能。
李老师:不错,那负载因子默认是多少?扩容机制呢?
谢飞机:0.75!容量不够就翻倍,然后重新哈希……大概吧。
李老师(点头):还行。ArrayList 和 LinkedList 区别?
谢飞机:一个数组实现,查询快;一个双向链表,增删快!
李老师:很好。那 ArrayList 扩容是扩多少?
谢飞机:1.5 倍?我记不清了……但肯定不是翻倍!
李老师:勉强过关。
第二轮:并发与框架开始发难
李老师:线程池的核心参数有哪些?
谢飞机:corePoolSize、maxPoolSize、workQueue……还有个 keepAliveTime!
李老师:execute() 和 submit() 有什么区别?
谢飞机:submit 可以返回结果?用 Future 拿……execute 就是丢进去跑。
李老师:Spring 中 Bean 的作用域有哪些?
谢飞机:singleton、prototype……request、session……还有 application!
李老师:Bean 循环依赖怎么解决的?
谢飞机:啊?就是……互相引用嘛,Spring 用三级缓存……提前暴露?我有点乱……
李老师(皱眉):继续。MyBatis #{} 和 ${} 什么区别?
谢飞机:#{} 是预编译,防 SQL 注入!${} 是直接拼接……像 String.format!
李老师:算你答对。
第三轮:分布式与架构压轴轰炸
李老师:Dubbo 的调用流程?
谢飞机:消费者找注册中心拿提供者地址,然后 RPC 调用……用 Netty 通信?
李老师:Redis 持久化机制?
谢飞机:RDB 快照,AOF 日志追加……混合持久化是 4.0 后的?
李老师:MySQL 索引失效场景?
谢飞机:左模糊 like '%xx',类型转换,or 条件不用索引……函数操作字段也不行!
李老师:xxl-job 如何保证任务不重复执行?
谢飞机:呃……调度中心只派一个?分布式锁?我用的时候没注意……
李老师:DDD 中聚合根的作用?
谢飞机:就是……管理一堆实体?保证一致性?不能跨聚合直接改……我项目没真用过……
李老师(合上简历):今天先到这里,你回去等通知吧。
谢飞机(起身傻笑):好嘞!我这表现应该稳了吧?
参考答案详解
1. HashMap 底层结构
- JDK8 之前:数组 + 链表
- JDK8 之后:数组 + 链表/红黑树(链表长度 ≥8 且数组长度 ≥64 才转红黑树)
- 负载因子默认 0.75,初始容量 16,扩容为原容量 2 倍
- put 流程:hash 计算位置 → 无冲突直接插入 → 冲突则链表或红黑树插入 → 判断是否扩容
2. ArrayList 扩容机制
- 默认初始容量 10
- 扩容为当前容量的 1.5 倍(oldCapacity + (oldCapacity >> 1))
- 使用 grow() 方法,通过 Arrays.copyOf() 实现扩容
3. 线程池核心参数
- corePoolSize:核心线程数
- maxPoolSize:最大线程数
- workQueue:任务队列
- keepAliveTime:非核心线程空闲存活时间
- threadFactory:线程创建工厂
- handler:拒绝策略
4. execute vs submit
- execute(Runnable):无返回值,异常会抛出
- submit(Callable/Runnable):返回 Future,可获取结果或异常
5. Spring Bean 作用域
- singleton:单例(默认)
- prototype:每次获取新实例
- request/session/application:Web 相关作用域
- websocket:WebSocket 作用域
6. 循环依赖解决
- Spring 使用三级缓存:
- singletonObjects:单例池
- earlySingletonObjects:早期暴露对象
- singletonFactories:单例工厂
- 提前暴露 ObjectFactory 解决 A→B→A 依赖
7. MyBatis #{} 与 ${}
- #{}:预编译处理,占位符 ?,防 SQL 注入
- ${}:字符串拼接,直接替换,有注入风险,适合动态表名、排序字段
8. Dubbo 调用流程
- 服务提供者启动并注册服务到注册中心(ZooKeeper/Nacos)
- 消费者订阅服务,获取提供者列表
- 消费者基于负载均衡选择节点
- 通过 Netty 进行 RPC 调用
- 支持集群容错、熔断、限流等机制
9. Redis 持久化
- RDB:定时快照,恢复快,可能丢失数据
- AOF:记录写命令,日志追加,更安全,文件大
- 混合持久化(AOF + RDB):fork 子进程生成 RDB 快照,后续命令追加到 AOF
10. MySQL 索引失效场景
- 左模糊:LIKE '%abc'
- 类型转换:字符串字段传数字
- OR 条件:部分条件无索引
- 函数操作:WHERE YEAR(create_time) = 2024
- 最左前缀原则破坏:联合索引未从最左开始使用
11. xxl-job 任务去重
- 调度中心通过数据库锁(如 SELECT FOR UPDATE)保证同一任务在同一时间只被触发一次
- 执行器支持失败重试,但任务逻辑需保证幂等性
12. DDD 聚合根
- 聚合是一组业务上紧密关联的对象集合
- 聚合根是外部访问聚合的唯一入口
- 聚合内部保持一致性,通过领域事件实现跨聚合通信
- 聚合根负责维护业务规则和不变性约束