Java面试官与谢飞机的三轮技术拷问:从HashMap到DDD的爆笑对决

6 阅读1分钟

面试现场:大厂Java岗,谢飞机登场

面试官(推了推眼镜):请做个自我介绍。

谢飞机:我叫谢飞机,擅长起飞,落地不太稳……但代码从不炸机!


第一轮:Java基础 & 集合框架

Q1:说说 HashMap 的底层结构?

谢飞机:数组 + 链表,JDK8 后链表长度超 8 变红黑树!

面试官:不错,有点东西。

Q2:那 ConcurrentHashMap 如何保证线程安全?

谢飞机:synchronized 锁整个 map!

面试官:……JDK7 是分段锁,JDK8 是 CAS + synchronized 控制桶头节点,你这锁全表,系统得卡成PPT。

Q3:ArrayList 和 LinkedList 区别?

谢飞机:一个基于数组,查询快;一个基于链表,增删快!

面试官:还行,勉强过关。


第二轮:并发编程 & 中间件

Q4:线程池的核心参数有哪些?

谢飞机:corePoolSize、maxPoolSize、workQueue、threadFactory、handler!背过!

面试官:可以,那你来说说拒绝策略?

谢飞机:比如 AbortPolicy,就是直接干掉任务……哦不,抛异常!

面试官:还知道其他吗?

谢飞机:CallerRunsPolicy,让主线程自己跑……还有……还有……我运行一下脑子——超时了!

Q5:Redis 的持久化机制?

谢飞机:RDB 是拍快照,AOF 是记日志,append only!

面试官:那两者如何选择?

谢飞机:看脸……啊不是,看业务!数据重要用 AOF,性能优先用 RDB!

面试官:勉强及格。


第三轮:Spring生态 & 架构设计

Q6:SpringBoot 自动装配原理?

谢飞机:@EnableAutoConfiguration,扫描 META-INF/spring.factories,条件装配!

面试官:不错,有准备。

Q7:MyBatis #{} 和 ${} 区别?

谢飞机:#{} 防 SQL 注入,${} 拼接字符串,要小心XSS!

面试官:嗯,安全意识还可以。

Q8:DDD 中的聚合根是什么?

谢飞机:就是……很多模块聚在一起,像个领导一样管理大家……

面试官:……你这是团建吧?

Q9:Dubbo 的调用流程?

谢飞机:消费者找注册中心,拿到提供者地址,然后 RPC 调用,走的是 Netty!

面试官:还行,底层通信知道。


面试官(合上笔记本):今天就到这里,你的水平……我们回去讨论一下,回家等通知吧

谢飞机(小声):等通知=没通知,又要重新起飞了……


参考答案详解

Q1:HashMap 底层结构

  • JDK8 前:数组 + 链表
  • JDK8 后:数组 + 链表 + 红黑树(链表长度 ≥ 8 且数组长度 ≥ 64)
  • 扩容机制:负载因子 0.75,触发扩容为原容量 2 倍
  • hash 冲突:通过扰动函数减少碰撞

Q2:ConcurrentHashMap 线程安全

  • JDK7:Segment 分段锁,继承 ReentrantLock
  • JDK8:CAS + synchronized 锁桶的头节点,降低锁粒度,性能更高
  • 使用 volatile 保证可见性

Q3:ArrayList vs LinkedList

  • ArrayList:基于动态数组,支持随机访问 O(1),扩容成本高,插入删除慢
  • LinkedList:双向链表,插入删除 O(1),遍历慢,占用内存多(前后指针)

Q4:线程池核心参数

  1. corePoolSize:核心线程数
  2. maxPoolSize:最大线程数
  3. keepAliveTime:非核心线程空闲存活时间
  4. workQueue:任务队列(如 LinkedBlockingQueue)
  5. threadFactory:线程创建工厂
  6. handler:拒绝策略

Q5:线程池拒绝策略

  • AbortPolicy:抛出 RejectedExecutionException(默认)
  • CallerRunsPolicy:由提交任务的线程执行该任务
  • DiscardPolicy:默默丢弃任务
  • DiscardOldestPolicy:丢弃队列中最老的任务,重试提交当前任务

Q6:Redis 持久化

  • RDB:定时快照,恢复快,可能丢失数据
  • AOF:记录每条写命令,appendonly.aof 文件,可配置 fsync 策略(everysec 最常用)
  • 混合使用:Redis 4.0+ 支持 AOF 重写时包含 RDB 格式数据

Q7:SpringBoot 自动装配

  • @SpringBootApplication → @EnableAutoConfiguration
  • SpringFactoriesLoader 加载 META-INF/spring.factories 中的自动配置类
  • 条件注解:@ConditionalOnClass、@ConditionalOnMissingBean 等控制是否生效

Q8:MyBatis #{} 与 ${}

  • #{}:预编译处理,PreparedStatement 参数占位,防 SQL 注入
  • ${}:字符串拼接,直接替换,需手动过滤特殊字符,用于动态表名、排序字段等

Q9:DDD 聚合根(Aggregate Root)

  • 聚合:一组相关对象的集合,作为一个数据修改单元
  • 聚合根:聚合的根实体,外部只能通过聚合根访问内部对象
  • 保证一致性边界,避免脏数据,常用于复杂业务模型设计

Q10:Dubbo 调用流程

  1. 服务提供者启动,注册服务到注册中心(Zookeeper/Nacos)
  2. 消费者启动,订阅注册中心服务列表
  3. 消费者通过代理发起调用,路由选择提供者
  4. Netty 进行网络通信,序列化传输
  5. 提供者执行方法,返回结果
  6. 支持负载均衡、熔断、限流等高级特性