java 常面试的10道题及答案

152 阅读7分钟

以下是 Java 面试高频 10 道题 + 精炼答案(覆盖基础核心、JVM、并发、集合等重点,适合面试快速记忆):

1. 谈谈 Java 的三大特性(封装、继承、多态)

  • 封装:隐藏对象内部实现细节,通过 ​​private​​ 限制访问,提供 ​​getter/setter​​ 等公共方法交互,降低耦合、提高安全性(比如实体类的属性封装)。
  • 继承:子类通过 ​​extends​​ 继承父类非私有属性和方法,实现代码复用;但 Java 只支持单继承(避免菱形依赖),可通过接口间接实现多继承。
  • 多态:同一行为的不同表现形式,核心是「方法重写(子类覆写父类方法)」和「向上转型(父类引用指向子类对象)」,比如 ​​List list = new ArrayList<>()​​,调用 ​​list.add()​​ 时实际执行 ArrayList 的实现,提高代码灵活性。

2. String、StringBuffer、StringBuilder 的区别

特性StringStringBufferStringBuilder
可变性不可变(final 修饰字符数组)可变(数组扩容)可变(数组扩容)
线程安全安全(无修改操作)安全(方法加 ​​synchronized​​)不安全(无锁)
效率最低(修改会创建新对象)中等最高
适用场景少量字符串操作多线程环境字符串拼接单线程环境字符串拼接

3. 什么是 JVM 内存模型?主要分区有哪些?

JVM 内存模型(JMM)定义了线程如何通过内存交互,解决多线程可见性、原子性、有序性问题; 核心分区(基于 HotSpot 虚拟机):

  • 程序计数器:线程私有,记录当前线程执行的字节码行号,无 OOM 可能。
  • 虚拟机栈:线程私有,存储方法调用的栈帧(局部变量、操作数栈等),栈深度溢出会抛 ​​StackOverflowError​​,扩容失败抛 ​​OutOfMemoryError​​。
  • 本地方法栈:线程私有,为 Native 方法(如 ​​System.currentTimeMillis()​​)提供内存支持,同样可能抛 StackOverflowError/OOM。
  • :线程共享,存储对象实例和数组,是 GC 主要区域(分年轻代、老年代),OOM 高频发生区。
  • 方法区:线程共享,存储类信息、常量、静态变量等(JDK 8 后用元空间 Metaspace 实现,占用本地内存,默认无上限)。

4. 什么是 GC(垃圾回收)?常见 GC 算法和收集器有哪些?

  • GC 定义:自动回收堆中“不可达对象”(无引用指向的对象)的内存,避免内存泄漏,无需手动释放。
  • 核心算法
  • 标记-清除:先标记垃圾,再清除,效率低、会产生内存碎片。
  • 复制算法:将内存分为两块,存活对象复制到另一块,清除原块,无碎片、效率高(年轻代默认用)。
  • 标记-整理:标记后将存活对象向一端移动,再清除剩余区域(老年代默认用)。
  • 常见收集器
  • 年轻代:SerialGC(串行,单线程)、Parallel Scavenge(并行,注重吞吐量)。
  • 老年代:Serial Old(串行)、Parallel Old(并行)、CMS(并发,注重响应时间)、G1(区域分代,兼顾吞吐量和响应时间)。

5. Java 中实现多线程的三种方式及区别

  • 方式 1:继承 Thread 类:重写 ​​run()​​ 方法,调用 ​​start()​​ 启动线程(底层调用 ​​start0()​​ native 方法)。 缺点:单继承限制,无法继承其他类。
  • 方式 2:实现 Runnable 接口:实现 ​​run()​​ 方法,通过 ​​new Thread(runnable).start()​​ 启动。 优点:无继承限制,可实现多个接口;缺点:无法直接获取返回值。
  • 方式 3:实现 Callable 接口:实现 ​​call()​​ 方法(可返回值、抛异常),结合 ​​FutureTask​​ 包装,通过线程池启动。 优点:支持返回值和异常处理,适合异步任务;缺点:代码稍复杂。

6. 什么是线程安全?如何保证线程安全?

  • 线程安全:多线程并发访问共享资源时,不会出现数据错乱、死锁等问题(比如多线程抢票,不会出现超卖、重复售票)。
  • 实现方式
  1. 锁机制:​​synchronized​​(关键字,可修饰方法/代码块,底层是监视器锁)、​​ReentrantLock​​(类锁,支持公平锁/非公平锁、可中断)。
  2. 无锁机制:​​volatile​​(修饰变量,保证可见性和有序性,不保证原子性)、原子类(​​AtomicInteger​​,基于 CAS 实现原子操作)。
  3. 线程封闭:局部变量(线程私有,无共享)、ThreadLocal(每个线程独立存储副本,避免共享)。
  4. 并发容器:​​ConcurrentHashMap​​(分段锁/CAS 实现线程安全)、​​CopyOnWriteArrayList​​(写时复制,读无锁)。

7. HashMap 和 ConcurrentHashMap 的区别(JDK 8+)

特性HashMapConcurrentHashMap
线程安全不安全(多线程put可能扩容死循环、数据丢失)安全
实现方式数组+链表/红黑树(链表长度>8转红黑树)数组+链表/红黑树+CAS+synchronized(分段锁优化为节点锁)
支持操作无原子操作,需手动加锁支持 ​​putIfAbsent​​ 等原子操作
遍历特性快速失败(modCount校验,并发修改抛 ConcurrentModificationException)弱一致性(遍历不抛异常,可能读取旧数据)
适用场景单线程环境多线程并发环境

8. 什么是异常体系?Checked Exception 和 Unchecked Exception 的区别

  • 异常体系:顶层是 ​​Throwable​​,分为 ​​Error​​(错误,如 ​​OutOfMemoryError​​,JVM 层面,无法捕获修复)和 ​​Exception​​(异常,可处理)。
  • Checked Exception(受检异常) :编译期强制检查,必须捕获或声明抛出(如 ​​IOException​​、​​SQLException​​),避免遗漏处理。
  • Unchecked Exception(非受检异常) :编译期不检查,继承自 ​​RuntimeException​​(如 ​​NullPointerException​​、​​ArrayIndexOutOfBoundsException​​),通常是代码逻辑错误,无需强制捕获,建议通过代码优化避免。

9. 谈谈你对 Spring IoC 和 AOP 的理解

  • IoC(控制反转)
  • 核心:将对象的创建、依赖注入交给 Spring 容器管理,而非手动 ​​new​​ 对象,降低组件耦合。
  • 实现:通过 XML 配置、注解(​​@Component​​、​​@Autowired​​)或 Java 配置类定义 Bean,容器启动时初始化 Bean 并注入依赖。
  • 好处:解耦、便于测试(可替换依赖的模拟对象)、提高代码复用。
  • AOP(面向切面编程)
  • 核心:在不修改原有代码的前提下,对方法进行增强(如日志、事务、权限校验),将通用逻辑抽离为“切面”。
  • 关键概念:切点(Pointcut,指定增强的方法)、通知(Advice,增强的逻辑,如 ​​@Before​​、​​@AfterReturning​​)、切面(Aspect,切点+通知)、动态代理(JDK 动态代理基于接口,CGLIB 基于子类,Spring 自动选择)。
  • 应用:Spring 事务管理(​​@Transactional​​)、全局日志打印、接口权限拦截。

10. 什么是分布式事务?常见解决方案有哪些?

  • 分布式事务:跨多个服务/数据库的事务(如下单流程:扣库存、减余额、创建订单分属不同服务),需保证“所有操作成功或所有失败”,满足 ACID 特性。
  • 常见解决方案
  1. 2PC(两阶段提交):分为准备阶段(所有参与者确认可提交)和提交阶段(协调者通知提交),缺点是阻塞、协调者单点故障。
  2. TCC(Try-Confirm-Cancel):业务层实现 Try(资源检查预留)、Confirm(确认提交)、Cancel(回滚释放),无锁、高性能,缺点是代码侵入性强。
  3. 本地消息表+MQ:本地事务和消息表原子提交,通过 MQ 异步通知其他服务,失败则重试,适合最终一致性场景(如订单通知)。
  4. Saga 模式:将分布式事务拆分为多个本地事务,每个事务失败时执行补偿操作,适合长事务(如物流履约)。
  5. 事务消息(RocketMQ 支持):MQ 保证消息可靠投递,接收方确认后才提交本地事务,简化一致性实现。

这些题目覆盖了 Java 基础、JVM、并发、集合、Spring 框架、分布式核心考点,答案简洁且直击要点,面试时可结合实际项目经验补充案例(比如“项目中用 ConcurrentHashMap 解决了多线程统计问题”),效果更好。