一、Java核心基础考点剖析

String、HashMap与集合框架的底层实现

在回顾java面试题2015的真题时,我们发现面试官对基础数据结构的考察依然占据主导地位。特别是String类的不可变性设计、HashMap在JDK1.7与1.8版本中的差异,以及ArrayList与LinkedList的性能对比,是每次面试必问的重灾区。

1.1 String类的不可变性及其优势

String类被final修饰,其内部字符数组也被final修饰,这意味着一旦创建,其内容不可更改。这种设计带来了三大优势:1. 常量池优化;2. 线程安全;3. 支持HashMap等集合的高效存储。

1.2 HashMap底层原理演进

在2015年的面试中,JDK1.7的HashMap是重点。它由数组+链表组成,通过哈希碰撞解决冲突。而JDK1.8引入了红黑树,当链表长度超过阈值(默认为8)且数组长度超过64时,链表转换为红黑树,将查找时间复杂度从O(n)降低到O(log n)。

特性 JDK 1.7 HashMap JDK 1.8 HashMap
数据结构 数组 + 链表 数组 + 链表 + 红黑树
哈希冲突解决 链表 链表转红黑树(长度>8)
扩容时机 达到阈值前扩容 达到阈值时扩容
线程安全性 非线程安全 非线程安全

1.3 集合框架的选择

ArrayList基于动态数组实现,支持随机访问,插入删除效率低;LinkedList基于双向链表,插入删除效率高,但随机访问慢。在实际开发中,除非有频繁的头部插入删除操作,否则优先选择ArrayList。

二、JVM内存模型与垃圾回收

OOM排查与GC算法详解

JVM是Java工程师进阶的必经之路。在java面试题2015中,关于内存溢出(OOM)和垃圾回收(GC)算法的问题占据了相当大的比重。理解堆内存划分、GC Roots判定以及常用GC收集器的工作原理,是解决线上故障的关键。

常见垃圾收集算法

  • 【标记-清除】:分为标记和清除两个阶段,缺点是可以产生大量内存碎片。
  • 【复制算法】:将内存分为两块,每次只用其中一块,垃圾回收时将存活对象复制到另一块。适用于对象存活率低的场景(如新生代)。
  • 【标记-整理】:标记后让所有存活对象向一端移动,然后清理边界外的内存。适用于对象存活率高的场景(如老年代)。

Java内存区域划分

JVM内存主要分为线程私有区域和线程共享区域:

  1. 程序计数器:线程私有,记录当前线程执行的字节码行号。
  2. Java虚拟机栈:线程私有,描述Java方法执行的内存模型,存储局部变量表、操作数栈等。
  3. 本地方法栈:线程私有,为Native方法服务。
  4. Java堆:线程共享,是GC的主要区域,分为新生代和老年代。
  5. 方法区:线程共享,存储类信息、常量、静态变量等。

常用JVM调优参数

-Xms1g -Xmx1g  # 初始堆大小和最大堆大小设为1GB
-XX:NewRatio=2  # 老年代与新生代比例为2:1
-XX:SurvivorRatio=8 # Eden与Survivor比例为8:1
-XX:+UseG1GC  # 启用G1垃圾收集器
-XX:+PrintGCDetails # 打印GC详细信息
                            

三、Java并发编程(JUC)

线程池、锁机制与CAS原理

随着多核CPU的普及,并发编程成为Java面试的高频考点。在java面试题2015中,线程池的配置、synchronized与ReentrantLock的区别、以及volatile关键字的内存语义是必问内容。

线程池核心参数

创建线程池需关注7大参数:

  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数
  • keepAliveTime:空闲线程存活时间
  • unit:时间单位
  • workQueue:任务队列
  • threadFactory:线程工厂
  • handler:拒绝策略

锁的演进

从偏向锁→轻量级锁→重量级锁的升级过程,体现了JVM对锁竞争的优化。synchronized是重量级锁,依赖Monitor对象;ReentrantLock基于AQS,支持公平锁和中断响应。

CAS与ABA问题

CAS(Compare And Swap)是乐观锁的基础,包含三个操作数:内存值V、旧的预期值A、要更新的新值B。当且仅当V==A时,更新V=B,否则重试。ABA问题可通过AtomicStampedReference解决。

四、主流框架原理(Spring/MyBatis)

AOP、IOC与动态代理

Spring框架作为Java EE的事实标准,其IOC(控制反转)和AOP(面向切面编程)是面试的核心。2015年,Spring MVC与MyBatis的组合非常流行,理解其工作原理有助于深入掌握企业级开发。

4.1 Spring IOC与AOP

IOC:将对象的创建和依赖关系的管理交给Spring容器,通过DI(依赖注入)实现解耦。核心实现是工厂模式和反射。

AOP:将横切关注点(如日志、事务)与业务逻辑分离。Spring AOP基于动态代理实现:如果目标对象实现了接口,使用JDK动态代理;否则使用CGLIB。

4.2 MyBatis缓存机制

MyBatis提供一级缓存(SqlSession级别,默认开启)和二级缓存(Mapper级别,需手动开启)。一级缓存基于PerpetualCache,使用HashMap实现;二级缓存基于Cache接口,可自定义实现。

对比项 JDK动态代理 CGLIB动态代理
原理 基于接口 基于继承
性能 早期较慢,JDK8后优化 早期较快,JDK8后差异不大
限制 目标类必须实现接口 目标类不能是final类或final方法

五、数据库与SQL优化

索引原理、事务隔离与慢查询分析

MySQL作为主流关系型数据库,其索引结构和事务隔离级别是面试的常客。在java面试题2015中,B+树索引的优势、覆盖索引、最左前缀原则以及事务的ACID特性是重点。

5.1 B+树索引优势

MySQL InnoDB引擎默认使用B+树索引。相比B树,B+树所有数据存储在叶子节点,非叶子节点只存储键值,使得树更矮胖,减少IO次数。同时,叶子节点通过双向链表连接,适合范围查询。

5.2 事务隔离级别

  • 读未提交(Read Uncommitted):可能发生脏读。
  • 读已提交(Read Committed):Oracle默认,解决脏读,可能发生不可重复读。
  • 可重复读(Repeatable Read):MySQL默认,解决脏读和不可重复读,通过MVCC和Next-Key Lock解决幻读。
  • 串行化(Serializable):最高级别,解决所有问题,但性能最低。

5.3 慢查询优化

使用EXPLAIN分析SQL执行计划,关注type(访问类型)、key(实际使用的索引)、rows(扫描行数)和Extra(额外信息)。避免使用SELECT ,尽量使用覆盖索引。