⚡ 集合框架核心考点: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 常被问及。它有两个主要作用:
- 保证可见性: 当一个线程修改了变量,其他线程立即可见。
- 禁止指令重排序: 通过插入内存屏障实现。
- 不保证原子性: 例如 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): 老年代常用,无碎片。
- 分代收集: 结合上述算法,年轻代用复制,老年代用标记-清除或整理。
类加载过程
- 加载: 将 .class 文件字节码加载到内存。
- 验证: 确保字节码文件符合 JVM 规范。
- 准备: 为静态变量分配内存并设置默认值。
- 解析: 将符号引用替换为直接引用。
- 初始化: 执行 static 块和静态变量赋值。
🌱 Spring 框架核心原理
Spring 是 Java 开发的事实标准。中级面试重点考察 IoC、AOP 原理以及 Spring Boot 的自动配置机制。
1. IoC 与 AOP 深度理解
IoC (控制反转): 将对象的创建权交给 Spring 容器,通过 DI (依赖注入) 实现解耦。主要实现方式是反射。
AOP (面向切面编程): 将日志、事务、权限等横切关注点从业务逻辑中分离。底层基于动态代理:
- 如果目标对象实现了接口,默认使用 JDK 动态代理。
- 如果目标对象没有实现接口,使用 CGLIB 动态代理。
2. Spring Bean 的生命周期
Spring 容器通过构造器或工厂方法创建 Bean 实例。
注入 Bean 依赖的属性,执行 setter 方法或字段注入。
执行 Aware 接口方法(如 BeanNameAware),然后执行 InitializingBean 的 afterPropertiesSet 方法,最后执行自定义 init-method。
容器关闭时,执行 DisposableBean 的 destroy 方法或自定义 destroy-method。
🗄️ 数据库优化与索引原理
MySQL 是后端开发最常用的数据库。索引优化和 SQL 调优是中级面试的必考题。
1. B+树索引结构
MySQL InnoDB 引擎默认使用 B+树作为索引结构。相比 B 树,B+树的所有数据都存储在叶子节点,非叶子节点只存储键值,因此非叶子节点可以存储更多键值,树的高度更低,I/O 次数更少。
2. 索引失效场景
在 java中级面试题及答案整理 中,以下情况会导致索引失效:
- 对索引列进行函数运算或表达式计算。
- 模糊查询以 % 开头(如 LIKE '%abc')。
- 类型隐式转换(如字符串不加引号)。
- OR 条件中,只要有一个条件没有索引,整个查询都会失效。
📌 慢查询优化思路
- 开启慢查询日志。
- 使用 EXPLAIN 分析执行计划。
- 关注 key 字段,确认是否使用了索引。
- 关注 rows 字段,估算扫描行数。
- 关注 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 核心组件的使用和基本原理。