⚡ 集合框架核心考点:HashMap 与 ConcurrentHashMap

在 java中级面试题及答案整理 中,集合框架永远是最基础的考察点。面试官通常不会只问“HashMap 怎么用”,而是会深入到底层数据结构、扩容机制以及线程安全问题上。

1. HashMap 底层数据结构演变

Java 7 中,HashMap 由数组+链表组成。Java 8 引入了红黑树,当链表长度超过 8 且数组长度超过 64 时,链表转化为红黑树,以提高查询效率(从 O(n) 提升到 O(log n))。

📌 核心特性:Java 7 vs Java 8

  • Java 7: 数组 + 链表。头插法,多线程下扩容可能产生死循环。
  • Java 8: 数组 + 链表 + 红黑树。尾插法,解决死循环问题,优化查询性能。

📌 扩容机制 (Resize)

默认初始容量 16,负载因子 0.75。当元素数量达到 16 0.75 = 12 时触发扩容,容量翻倍。扩容时需要重新计算 Hash 值,但在 Java 8 中可以通过位运算优化。

2. ConcurrentHashMap 如何保证线程安全?

这是 java中级面试题及答案整理 中的高频难点。JDK 1.7 使用分段锁(Segment),JDK 1.8 使用 CAS + synchronized 保证线程安全。

// 示例:ConcurrentHashMap 的基本使用
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class ConcurrentHashMapDemo {
    public static void main(String[] args) {
        ConcurrentMap<String, String> map = new ConcurrentHashMap<>();
        map.put("key1", "value1");
        // putIfAbsent 原子操作,防止覆盖
        map.putIfAbsent("key2", "value2");
        System.out.println(map.get("key1"));
    }
}

⚙️ 多线程与并发编程:JUC 包深度解析

中级开发必须掌握并发编程的基础。除了 synchronized 和 volatile,JUC 包下的工具类更是面试的重灾区。

1. 线程池七大参数与工作流程

面试官常问:“为什么不建议使用 Executors 创建线程池?” 答案在于其底层可能引发 OOM(内存溢出)。

参数名称 说明 默认值/示例
corePoolSize 核心线程数 根据 CPU 密集型/I/O 密集型计算
maximumPoolSize 最大线程数 corePoolSize + N
keepAliveTime 空闲线程存活时间 60s
workQueue 任务队列 ArrayBlockingQueue, LinkedBlockingQueue
threadFactory 线程工厂 自定义命名,便于排查问题
handler 拒绝策略 AbortPolicy, CallerRunsPolicy

2. volatile 关键字的作用

在 java中级面试题及答案整理 中,volatile 常被问及。它有两个主要作用:

  1. 保证可见性: 当一个线程修改了变量,其他线程立即可见。
  2. 禁止指令重排序: 通过插入内存屏障实现。
  3. 不保证原子性: 例如 i++ 操作,volatile 无法保证线程安全。

🔥 JVM 内存模型与垃圾回收

理解 JVM 是中级开发晋升高级开发的必经之路。面试中常结合线上 OOM 或 CPU 飙升问题来考察。

JVM 内存区域划分

  • 线程私有: 程序计数器、Java 虚拟机栈、本地方法栈。
  • 线程共享: 堆(Heap)、方法区(Metaspace)。
  • 堆: 存放对象实例,是 GC 的主要区域。分为 Young Gen 和 Old Gen。
  • Young Gen: 分为 Eden 和 Survivor 区(S0, S1)。

常见垃圾回收算法

  • 标记-清除 (Mark-Sweep): 产生内存碎片。
  • 复制 (Copying): Eden:S0:S1 = 8:1:1,高效无碎片。
  • 标记-整理 (Mark-Compact): 老年代常用,无碎片。
  • 分代收集: 结合上述算法,年轻代用复制,老年代用标记-清除或整理。

类加载过程

  1. 加载: 将 .class 文件字节码加载到内存。
  2. 验证: 确保字节码文件符合 JVM 规范。
  3. 准备: 为静态变量分配内存并设置默认值。
  4. 解析: 将符号引用替换为直接引用。
  5. 初始化: 执行 static 块和静态变量赋值。

🌱 Spring 框架核心原理

Spring 是 Java 开发的事实标准。中级面试重点考察 IoC、AOP 原理以及 Spring Boot 的自动配置机制。

1. IoC 与 AOP 深度理解

IoC (控制反转): 将对象的创建权交给 Spring 容器,通过 DI (依赖注入) 实现解耦。主要实现方式是反射。

AOP (面向切面编程): 将日志、事务、权限等横切关注点从业务逻辑中分离。底层基于动态代理:

2. Spring Bean 的生命周期

Step 1: 实例化

Spring 容器通过构造器或工厂方法创建 Bean 实例。

Step 2: 属性赋值

注入 Bean 依赖的属性,执行 setter 方法或字段注入。

Step 3: 初始化

执行 Aware 接口方法(如 BeanNameAware),然后执行 InitializingBean 的 afterPropertiesSet 方法,最后执行自定义 init-method。

Step 4: 销毁

容器关闭时,执行 DisposableBean 的 destroy 方法或自定义 destroy-method。

🗄️ 数据库优化与索引原理

MySQL 是后端开发最常用的数据库。索引优化和 SQL 调优是中级面试的必考题。

1. B+树索引结构

MySQL InnoDB 引擎默认使用 B+树作为索引结构。相比 B 树,B+树的所有数据都存储在叶子节点,非叶子节点只存储键值,因此非叶子节点可以存储更多键值,树的高度更低,I/O 次数更少。

2. 索引失效场景

在 java中级面试题及答案整理 中,以下情况会导致索引失效:

📌 慢查询优化思路

  1. 开启慢查询日志。
  2. 使用 EXPLAIN 分析执行计划。
  3. 关注 key 字段,确认是否使用了索引。
  4. 关注 rows 字段,估算扫描行数。
  5. 关注 type 字段,性能顺序:system > const > eq_ref > ref > range > index > ALL。

❓ 网友常问问题 (FAQ)

Q: 如何判断自己是中级 Java 开发?

A: 能够独立负责模块开发,理解框架底层原理,具备基本的性能调优能力,熟悉数据库索引优化,了解分布式基本概念。

Q: java中级面试题及答案整理 中哪些最重要?

A: 集合框架(HashMap)、多线程(线程池、锁)、JVM(内存模型、GC)、Spring(IoC/AOP)、数据库(索引、事务)是五大核心板块。

Q: 面试前如何高效复习?

A: 建议先梳理知识体系,再针对薄弱环节深入源码。多做真题,模拟面试场景,注重表达逻辑。

Q: 是否需要掌握微服务?

A: 目前主流企业招聘都要求熟悉微服务生态,至少了解 Spring Cloud 核心组件的使用和基本原理。