场景:某互联网大厂Java后端岗位终面,面试官一脸严肃,谢飞机穿着拖鞋、拎着泡面桶走进会议室。
第一轮:基础不牢,地动山摇
面试官:谢同学,先聊聊 HashMap 吧,它的底层数据结构是什么?
谢飞机:哦!这个我知道!它是一个 Map,能存 key 和 value,比如我存个“泡面品牌”和“好吃程度”,超好用!
面试官(点头):嗯,那它是怎么解决哈希冲突的?
谢飞机:冲突?哦,就像两个泡面都叫“康师傅”,那就…放一起呗!(挠头)
面试官(皱眉):…那 JDK 1.8 之后有什么优化?
谢飞机:1.8?是不是加了红烧牛肉味?
面试官(扶额):……
第二轮:并发与框架,越问越懵
面试官:说说 synchronized 和 ReentrantLock 的区别?
谢飞机:synchronized 是…同步的,Lock 是…锁的。都差不多吧?反正我代码里都用 synchronized,因为…字母少!
面试官:那 Spring Boot 自动装配的原理呢?
谢飞机:自动装配?是不是像我泡面自动加热水?SpringBoot 很智能,它知道我要啥!
面试官:……那 Redis 缓存穿透怎么解决?
谢飞机:穿透?是不是有人偷看我缓存?那我给它加个密码!或者…放个假数据,骗黑客!
面试官(叹气):你这…也算歪打正着。
第三轮:深入底层,彻底翻车
面试官:JVM 的 G1 垃圾回收器有什么特点?
谢飞机:G1?是不是 Game 1?垃圾回收…就是删掉不用的变量,比如我昨天吃的泡面盒!
面试官:MySQL 的 InnoDB 为什么用 B+ 树而不是 B 树?
谢飞机:B+ 树?是不是比 B 树多加了个“+”号?那肯定更厉害!可能…叶子节点能连起来,查得快?(小声)
面试官:最后一个问题,说说 DDD(领域驱动设计)的核心概念。
谢飞机:DDD?是不是 Double Double Delicious?领域…就是我的工位区域?驱动…是鼠标?设计…我画过泡面包装!
面试官(站起身,微笑):谢同学,今天就到这里吧。你回去等通知,记得…把泡面桶扔了。
谢飞机(兴奋):谢谢面试官!我回去就扔!
技术答案详解(小白必看)
1. HashMap 原理
- 底层结构:JDK 1.8 前是数组 + 链表;1.8 后当链表长度 ≥8 且数组长度 ≥64 时,链表转为红黑树,提升查询效率(O(n) → O(log n))。
- 哈希冲突:通过链地址法(拉链法)解决,即相同哈希值的元素组成链表。
- 扩容机制:默认初始容量 16,负载因子 0.75。扩容时容量翻倍,重新计算元素位置(高位参与运算优化)。
2. synchronized vs ReentrantLock
- synchronized:JVM 内置关键字,自动加锁/释放,不可中断,非公平锁。
- ReentrantLock:API 层面的锁,需手动 lock/unlock,支持公平/非公平、可中断、超时、多条件变量。
3. Spring Boot 自动装配
- 原理:基于
@EnableAutoConfiguration,通过spring.factories文件加载META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中的自动配置类,结合@Conditional条件注解按需装配 Bean。
4. Redis 缓存穿透
- 问题:大量请求查询不存在的数据,绕过缓存直击数据库。
- 解决方案:
- 布隆过滤器:快速判断 key 是否存在。
- 缓存空值:对查询结果为空的 key 也缓存(设置短 TTL),防止重复穿透。
5. JVM G1 垃圾回收器
- 特点:面向服务端应用的垃圾回收器,将堆划分为多个 Region,可预测停顿时间(-XX:MaxGCPauseMillis),采用标记-整理算法避免内存碎片。
6. MySQL InnoDB 为何用 B+ 树
- B+ 树优势:
- 非叶子节点不存数据,单页可存更多索引,减少 I/O 次数。
- 叶子节点用双向链表连接,范围查询高效。
- 所有数据都在叶子节点,查询稳定(B 树可能在非叶子节点命中)。
7. DDD(领域驱动设计)核心概念
- 核心:通过通用语言(Ubiquitous Language)对齐业务与技术,划分限界上下文(Bounded Context)。
- 关键模式:
- 实体(Entity):有唯一标识的对象(如订单 ID)。
- 值对象(Value Object):无标识,属性决定相等性(如地址)。
- 聚合(Aggregate):一致性边界,由聚合根管理内部对象。
- 领域事件(Domain Event):表示业务发生的重要状态变更。
谢飞机虽搞笑,但技术不能马虎!建议读者结合答案深入理解,夯实基础,方能笑傲面试场!