面试官:你好,请简单介绍一下自己,以及你常用的 Java 技术栈。
求职者:您好,我有三年 Java 开发经验,主要使用 Spring Boot、MyBatis 和 Spring Cloud 构建微服务。熟悉 JVM 调优和多线程编程,近期项目中重点优化了接口响应时间和数据库连接池配置。
面试官:好的。先从基础开始:String s = new String("abc") 创建了几个对象?
求职者:如果字符串常量池中尚未存在 "abc",则会创建两个对象:一个在堆中(由 new 创建),另一个放入常量池。如果常量池已有 "abc",则只创建堆中的对象。
面试官:正确。那 HashMap 在 JDK 1.8 中做了哪些关键改进?
求职者:主要改进是从链表转红黑树。当某个桶中的链表长度达到 8 且数组长度不小于 64 时,链表会转换为红黑树,将最坏查询时间复杂度从 O(n) 优化到 O(log n)。同时,扩容时采用高低位链表拆分,减少 rehash 开销。
面试官:很好。面向对象的三大特性如何在你项目中体现?
求职者:在支付模块中,我通过封装隐藏了第三方支付 SDK 的细节;使用继承定义了 BaseOrder 和不同子类型订单;多态则体现在策略模式中,比如 AlipayStrategy 和 WechatPayStrategy 实现统一 PayStrategy 接口,由上下文动态调用。
面试官:接下来谈谈 JVM。如果线上应用频繁 Full GC,你会如何排查?
求职者:首先使用 jstat -gcutil <pid> 观察老年代使用率和 GC 频率;若老年代持续增长,用 jmap -dump 生成堆转储,通过 MAT 分析是否存在内存泄漏,比如静态 Map 未清理、缓存未设置过期等。我们曾因本地缓存无限增长导致问题,后来引入了 Caffeine 并设置最大容量。
面试官:多线程方面,volatile 能保证原子性吗?
求职者:不能。volatile 仅保证可见性和禁止指令重排序,但不保证复合操作的原子性。例如 i++ 包含读取、加一、写回三个步骤,即使 i 是 volatile 的,仍需使用 synchronized 或 AtomicInteger。
面试官:请手写一个线程安全的单例。
求职者:
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
面试官:正确,双重检查锁配合 volatile 防止指令重排。再问一下 Spring Bean 的生命周期?
求职者:从加载 BeanDefinition 开始,经历实例化、属性填充、执行 Aware 接口、BeanPostProcessor 前处理、初始化方法(如 @PostConstruct)、BeanPostProcessor 后处理(AOP 代理在此阶段生成),最后放入单例池。
面试官:最后,请实现链表反转(迭代方式)。
求职者:
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
面试官:代码清晰,边界处理得当。整体来看,你的基础扎实,对核心机制理解到位。建议后续可深入 JVM 调优参数(如 G1 的 Region 大小、Mixed GC 触发条件)在实际场景中的应用。
求职者:感谢您的反馈,这些正是我下一步计划深入的方向。谢谢您的时间。