Java 后端面试题精选:从基础到实战 1. 引言Java 后端开发岗位的面试通常涵盖 Java 基础、集合框架、并发编程、JVM、Spring 框架、数据库、分布式系统等多个维度。本文精选了 30 道高频面试题按难度递进组织并附上参考答案与解析思路帮助你在面试前系统梳理知识体系。2. Java 基础篇2.1 谈谈你对面向对象三大特性的理解封装将对象的属性和行为封装在类内部对外暴露必要的访问接口隐藏内部实现细节提高安全性和可维护性。继承子类复用父类的属性和方法实现代码复用同时可通过方法重写实现多态。多态同一操作作用于不同对象时产生不同行为。多态的实现依赖继承、方法重写和父类引用指向子类对象。2.2 String、StringBuilder、StringBuffer 的区别String不可变每次修改都会创建新对象线程安全因为不可变。StringBuilder可变非线程安全单线程下性能最高。StringBuffer可变线程安全方法加 synchronized性能略低于 StringBuilder。面试加分点String 不可变的底层原因是其内部char[]JDK 9 后为byte[]被final修饰且 String 类本身被final修饰不可被继承。2.3 与 equals() 的区别比较的是引用地址基本类型比较值。equals()默认也是比较引用地址但可被重写为比较内容。String 类重写了equals()所以abc.equals(abc)为 true。2.4 重载与重写的区别维度重载Overload重写Override发生位置同一个类中子类与父类之间方法签名参数列表必须不同参数列表必须相同返回类型可不同必须相同或为协变类型访问权限无限制不能低于父类方法的访问权限异常无限制不能抛出比父类更宽泛的异常3. 集合框架篇3.1 HashMap 的底层实现原理JDK 1.8 之后HashMap 底层采用数组 链表 红黑树的结构根据 key 的 hashCode 计算桶下标。若桶为空直接放入节点。若桶不为空发生哈希冲突以链表形式追加。当链表长度超过阈值默认 8且数组长度大于 64 时链表转为红黑树将查询复杂度从 O(n) 降为 O(log n)。扩容机制默认初始容量 16负载因子 0.75当元素数量超过容量 × 负载因子时触发扩容容量翻倍。3.2 HashMap 与 Hashtable 的区别线程安全Hashtable 线程安全方法加 synchronizedHashMap 非线程安全。null 值HashMap 允许 key 和 value 为 nullHashtable 不允许。初始容量HashMap 默认 16Hashtable 默认 11。底层结构HashMap 在 JDK 1.8 后引入红黑树Hashtable 没有。3.3 ConcurrentHashMap 如何保证线程安全JDK 1.7 采用分段锁Segment 继承 ReentrantLock将数据分为多个 Segment锁粒度较粗。JDK 1.8 放弃分段锁改用CAS synchronized只锁住单个桶的头节点锁粒度更细并发度更高。读操作通过 volatile 保证可见性无需加锁。3.4 ArrayList 与 LinkedList 的区别底层结构ArrayList 基于动态数组LinkedList 基于双向链表。随机访问ArrayList 通过下标 O(1) 访问LinkedList 需 O(n) 遍历。插入删除ArrayList 在中间插入/删除需移动元素LinkedList 只需修改指针。内存占用LinkedList 每个节点额外存储前后指针内存开销更大。4. 并发编程篇4.1 线程的创建方式有哪些继承 Thread 类。实现 Runnable 接口。实现 Callable 接口可返回结果、可抛异常。使用线程池ExecutorService。推荐使用线程池避免频繁创建销毁线程带来的性能开销。4.2 synchronized 与 ReentrantLock 的区别维度synchronizedReentrantLock实现方式JVM 层面monitorJDK 层面AQS锁的获取释放自动手动 lock/unlock可中断否是公平锁否可指定条件变量单一 wait/notify多个 Condition性能JDK 1.6 优化后与 Lock 相当灵活4.3 volatile 关键字的作用保证可见性volatile 修饰的变量每次读取都从主内存读取写入后立即刷新到主内存。禁止指令重排序volatile 写操作前的指令不会被重排到写之后。不保证原子性volatile 不能保证复合操作的原子性如i。4.4 线程池的核心参数有哪些ThreadPoolExecutor(intcorePoolSize,// 核心线程数intmaximumPoolSize,// 最大线程数longkeepAliveTime,// 空闲线程存活时间TimeUnitunit,// 时间单位BlockingQueueRunnableworkQueue,// 任务队列ThreadFactorythreadFactory,// 线程工厂RejectedExecutionHandlerhandler// 拒绝策略)执行流程核心线程满 → 任务入队列 → 队列满 → 创建非核心线程 → 达到最大线程数 → 执行拒绝策略。四种拒绝策略AbortPolicy抛异常、CallerRunsPolicy调用者执行、DiscardPolicy丢弃、DiscardOldestPolicy丢弃最旧任务。5. JVM 篇5.1 JVM 内存区域划分程序计数器当前线程执行的字节码行号指示器线程私有。虚拟机栈存储局部变量表、操作数栈等线程私有。本地方法栈为 native 方法服务线程私有。堆对象实例分配的主要区域线程共享GC 主要回收区域。方法区存储类信息、常量、静态变量JDK 8 后由元空间Metaspace替代永久代。5.2 垃圾回收算法有哪些标记-清除先标记可回收对象再统一回收。缺点产生内存碎片。标记-复制将内存分为两块只使用一块GC 时将存活对象复制到另一块。适合新生代。标记-整理标记后让存活对象向一端移动直接清理边界外内存。适合老年代。5.3 如何判断对象是否可被回收可达性分析算法从 GC Roots栈帧中的局部变量、静态变量、常量引用等出发向下搜索不可达的对象即为可回收对象。5.4 类加载过程包含哪些阶段加载 → 验证 → 准备 → 解析 → 初始化。其中验证、准备、解析合称为链接阶段。双亲委派模型类加载器收到加载请求时先委派给父类加载器父类无法完成时才由自己加载。目的是保证核心类库如 Object不被篡改。6. Spring 框架篇6.1 Spring 的 IOC 和 AOP 是什么IOC控制反转对象的创建和依赖关系的维护由容器管理而不是由对象自身创建依赖。通过依赖注入DI实现降低耦合度。AOP面向切面编程将日志、事务、权限等横切逻辑从业务代码中剥离通过动态代理在运行时织入实现关注点分离。6.2 Spring Bean 的生命周期实例化 → 属性赋值 → Aware 接口回调 → BeanPostProcessor 前置处理 → 初始化方法PostConstruct / InitializingBean→ BeanPostProcessor 后置处理 → 使用 → 销毁PreDestroy / DisposableBean。6.3 Spring 事务的传播行为有哪些REQUIRED默认支持当前事务不存在则新建。REQUIRES_NEW新建事务挂起当前事务。SUPPORTS有事务则加入无则非事务执行。NOT_SUPPORTED以非事务方式执行挂起当前事务。MANDATORY必须存在事务否则抛异常。NEVER必须不存在事务否则抛异常。NESTED嵌套事务基于保存点实现。6.4 Spring 如何解决循环依赖Spring 通过三级缓存解决单例 Bean 的循环依赖一级缓存完整 Bean 实例。二级缓存早期暴露的 Bean未完成属性填充。三级缓存Bean 工厂ObjectFactory用于生成代理对象。核心思路提前暴露半成品 Bean 的引用让依赖方先拿到引用后续再完成属性填充。7. 数据库篇7.1 索引失效的场景有哪些对索引列使用函数或计算。使用LIKE %xxx前缀模糊查询。隐式类型转换导致索引失效。使用OR连接非索引列。违反最左前缀原则联合索引。7.2 什么是事务的 ACID 特性原子性Atomicity事务要么全部成功要么全部回滚。一致性Consistency事务前后数据完整性约束不被破坏。隔离性Isolation并发事务之间相互隔离。持久性Durability事务提交后对数据的修改是永久的。7.3 MySQL 的隔离级别有哪些读未提交READ UNCOMMITTED可读到未提交数据存在脏读。读已提交READ COMMITTED只能读到已提交数据解决脏读存在不可重复读。可重复读REPEATABLE READ同一事务多次读取结果一致解决不可重复读存在幻读。MySQL 默认级别。串行化SERIALIZABLE完全串行执行解决幻读性能最低。7.4 什么是 MVCCMVCC多版本并发控制通过保存数据的历史版本实现读写不阻塞。InnoDB 通过隐藏字段trx_id、roll_pointer undo log ReadView实现在可重复读隔离级别下事务开启时生成 ReadView保证快照读的一致性。8. 分布式与微服务篇8.1 分布式事务的解决方案有哪些2PC两阶段提交准备阶段 提交阶段强一致性但存在阻塞和协调者单点问题。TCC补偿事务Try、Confirm、Cancel 三个阶段业务侵入性强最终一致性。本地消息表通过消息表 定时任务保证最终一致性。MQ 事务消息RocketMQ 等支持事务消息先发半消息本地事务成功后提交。8.2 什么是 CAP 定理一致性Consistency所有节点在同一时刻看到相同数据。可用性Availability每个请求都能得到响应。分区容错性Partition tolerance网络分区时系统仍能运行。分布式系统中三者不可兼得通常优先保证 AP如 Eureka或优先保证 CP如 ZooKeeper。8.3 如何设计一个高并发系统缓存Redis 缓存热点数据降低数据库压力。异步消息队列削峰填谷解耦系统。分库分表水平拆分数据提升读写性能。读写分离主库写、从库读提升吞吐量。限流熔断Sentinel / Hystrix 保护系统稳定性。集群部署负载均衡 水平扩容。9. 高频手撕代码题9.1 手写单例模式双重检查锁publicclassSingleton{privatestaticvolatileSingletoninstance;privateSingleton(){}publicstaticSingletongetInstance(){if(instancenull){synchronized(Singleton.class){if(instancenull){instancenewSingleton();}}}returninstance;}}volatile 防止指令重排序避免拿到未初始化完成的对象。9.2 手写 LRU 缓存importjava.util.LinkedHashMap;importjava.util.Map;publicclassLRUCacheK,VextendsLinkedHashMapK,V{privatefinalintcapacity;publicLRUCache(intcapacity){super(capacity,0.75f,true);this.capacitycapacity;}OverrideprotectedbooleanremoveEldestEntry(Map.EntryK,Veldest){returnsize()capacity;}}9.3 手写生产者消费者模型importjava.util.concurrent.ArrayBlockingQueue;importjava.util.concurrent.BlockingQueue;publicclassProducerConsumer{privatestaticfinalBlockingQueueIntegerqueuenewArrayBlockingQueue(10);staticclassProducerimplementsRunnable{Overridepublicvoidrun(){for(inti0;i100;i){try{queue.put(i);System.out.println(生产: i);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}}staticclassConsumerimplementsRunnable{Overridepublicvoidrun(){while(true){try{Integervaluequeue.take();System.out.println(消费: value);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}}publicstaticvoidmain(String[]args){newThread(newProducer()).start();newThread(newConsumer()).start();}}10. 面试技巧与总结10.1 答题思路建议先结论后展开先给出明确答案再补充原理和细节。结合项目经验回答时尽量关联实际项目场景体现解决问题的能力。主动延伸答完核心问题后可主动补充相关知识点展示知识深度。诚实面对盲区遇到不会的问题坦诚说明并表达学习意愿。10.2 复习路线建议夯实 Java 基础与集合源码。深入并发编程与 JVM 调优。掌握 Spring 核心原理与源码。熟悉 MySQL 索引、事务与锁机制。了解 Redis、消息队列等中间件。学习分布式理论与微服务实践。面试是知识积累的检验更是思维能力的体现。坚持系统化学习稳扎稳打祝你顺利拿到心仪的 Offer