Java 常见面试题(160道)
前言
本文整理了 160 道 Java 常见面试题,涵盖 Java 基础、集合、多线程、JVM、Spring、数据库、设计模式、分布式、算法等多个核心领域,旨在帮助读者系统复习,从容应对技术面试。
一、Java 基础(30道)
1. Java 语言有哪些特点?
面向对象、平台无关性、简单性、安全性、多线程、动态性、高性能、分布式支持。
2. JDK、JRE、JVM 的区别是什么?
- JDK (Java Development Kit):Java 开发工具包,包含 JRE 和开发工具(如编译器 javac)。
- JRE (Java Runtime Environment):Java 运行时环境,包含 JVM 和核心类库。
- JVM (Java Virtual Machine):Java 虚拟机,负责执行字节码,实现平台无关性。
3. == 和 equals() 的区别?
== 比较两个对象的引用地址是否相同;equals() 默认比较引用地址,但可被重写用于比较对象内容(如 String、Integer)。
4. final、finally、finalize 的区别?
- final:修饰类(不可继承)、方法(不可重写)、变量(常量)。
- finally:异常处理中,无论是否发生异常都会执行的代码块。
- finalize:Object 类的方法,垃圾回收前调用,不推荐使用。
5. String、StringBuffer、StringBuilder 的区别?
- String:不可变字符序列,线程安全。
- StringBuffer:可变字符序列,线程安全(方法 synchronized)。
- StringBuilder:可变字符序列,线程不安全,性能更高。
6. 重载(Overload)和重写(Override)的区别?
- 重载:同一类中,方法名相同,参数列表不同(类型、个数、顺序),与返回值、访问修饰符无关。
- 重写:子类重写父类方法,方法名、参数列表、返回值类型(或子类)相同,访问权限不能更严格,不能抛出更宽泛的异常。
7. 抽象类(abstract class)和接口(interface)的区别?
- 抽象类:可以有构造方法、成员变量、具体方法和抽象方法;单继承。
- 接口:Java 8 前只能有常量和抽象方法;Java 8 后可以有默认方法、静态方法;多实现。
8. List、Set、Map 的区别?
- List:有序、可重复。
- Set:无序、不可重复。
- Map:键值对,键不可重复。
9. ArrayList 和 LinkedList 的区别?
- ArrayList:基于动态数组,随机访问快(O(1)),增删慢(需移动元素)。
- LinkedList:基于双向链表,增删快(O(1)),随机访问慢(O(n))。
10. HashMap 的工作原理?
基于数组+链表/红黑树(JDK 8+)。通过 key 的 hashCode 计算数组下标,解决哈希冲突使用链表法,当链表长度超过阈值(默认 8)且数组长度≥64时,链表转为红黑树。
11. ConcurrentHashMap 如何保证线程安全?
JDK 7 使用分段锁(Segment);JDK 8 使用 synchronized + CAS 操作锁住数组的每个桶(Node),粒度更细,并发度更高。
12. 创建线程有哪几种方式?
- 继承 Thread 类,重写 run() 方法。
- 实现 Runnable 接口,实现 run() 方法。
- 实现 Callable 接口,结合 FutureTask。
- 使用线程池(ExecutorService)。
13. sleep() 和 wait() 的区别?
- sleep():Thread 类的静态方法,不释放锁,时间到自动恢复。
- wait():Object 类的方法,释放锁,需 notify()/notifyAll() 唤醒。
14. synchronized 和 ReentrantLock 的区别?
- synchronized:JVM 内置锁,自动释放,不可中断,非公平锁。
- ReentrantLock:API 级别锁,需手动释放,可中断,可设置公平/非公平,支持多个条件变量。
15. volatile 关键字的作用?
保证变量的可见性(直接读写主内存),禁止指令重排序,但不保证原子性。
16. 什么是 CAS?ABA 问题如何解决?
CAS(Compare And Swap)是一种无锁原子操作。ABA 问题指变量值从 A 变为 B 又变回 A,CAS 会误认为没变。解决:使用版本号(AtomicStampedReference)。
17. 线程池的核心参数?
- corePoolSize:核心线程数。
- maximumPoolSize:最大线程数。
- keepAliveTime:非核心线程空闲存活时间。
- workQueue:任务队列。
- threadFactory:线程工厂。
- handler:拒绝策略。
18. JVM 内存区域划分?
- 程序计数器:当前线程执行的字节码行号指示器。
- Java 虚拟机栈:存储局部变量表、操作数栈、动态链接、方法出口。
- 本地方法栈:为 Native 方法服务。
- 堆:存放对象实例,GC 主要区域。
- 方法区(元空间):存储类信息、常量、静态变量。
19. 垃圾回收算法有哪些?
- 标记-清除:产生内存碎片。
- 标记-整理:避免碎片,但移动对象成本高。
- 复制:将内存分为两块,每次使用一块,存活对象复制到另一块。
- 分代收集:根据对象存活周期将堆分为新生代(复制算法)和老年代(标记-清除/整理)。
20. 类加载过程?
- 加载:将类文件加载到内存。
- 验证:确保字节码安全。
- 准备:为静态变量分配内存并设置默认值。
- 解析:将符号引用转为直接引用。
- 初始化:执行静态代码块和静态变量赋值。
21. 双亲委派模型是什么?
类加载器收到加载请求后,先委派给父类加载器,只有当父类加载器无法完成时,子加载器才尝试加载。避免类重复加载,保证核心类安全。
22. Spring 框架的核心?
IoC(控制反转)和 AOP(面向切面编程)。
23. Spring Bean 的作用域?
- singleton:单例(默认)。
- prototype:每次请求创建新实例。
- request:每次 HTTP 请求创建一个。
- session:每个 HTTP Session 创建一个。
- global-session:全局 Session(Portlet 应用)。
24. Spring 事务传播行为?
- REQUIRED(默认):如果当前没有事务,就新建一个;如果已存在,则加入。
- REQUIRES_NEW:新建事务,挂起当前事务。
- SUPPORTS:有事务则加入,没有则以非事务执行。
- NOT_SUPPORTED:以非事务执行,挂起当前事务。
- MANDATORY:必须在一个事务中运行,否则抛异常。
- NEVER:必须在非事务中运行,否则抛异常。
- NESTED:如果当前存在事务,则在嵌套事务内执行。
25. Spring MVC 工作流程?
- 用户发送请求到前端控制器 DispatcherServlet。
- DispatcherServlet 调用 HandlerMapping 查找 Handler。
- 返回 HandlerExecutionChain(包含 Handler 和拦截器)。
- DispatcherServlet 调用 HandlerAdapter 执行 Handler。
- Handler 执行后返回 ModelAndView。
- DispatcherServlet 将 ModelAndView 传给 ViewResolver 解析。
- ViewResolver 返回 View。
- DispatcherServlet 渲染视图并返回给用户。
26. MyBatis 中 #{} 和 ${} 的区别?
- #{}:预编译处理,防止 SQL 注入,会自动加引号。
- ${}:字符串替换,有 SQL 注入风险,直接拼接到 SQL 中。
27. 数据库事务的 ACID 特性?
- 原子性(Atomicity):事务要么全部完成,要么全部不完成。
- 一致性(Consistency):事务前后数据库完整性约束不被破坏。
- 隔离性(Isolation):并发事务之间互不干扰。
- 持久性(Durability):事务提交后,对数据的修改是永久的。
28. 数据库隔离级别?
- 读未提交(Read Uncommitted):可能脏读、不可重复读、幻读。
- 读已提交(Read Committed):避免脏读,可能不可重复读、幻读。
- 可重复读(Repeatable Read):避免脏读、不可重复读,可能幻读(MySQL 默认,通过 MVCC 避免幻读)。
- 串行化(Serializable):最高隔离级别,避免所有问题,性能最低。
29. 索引失效的场景?
- 对索引列进行运算或函数操作。
- 使用 != 或 <>。
- 使用 OR 连接条件(除非所有列都有索引)。
- like 以通配符开头(如 ‘%abc’)。
- 字符串类型不加引号(隐式类型转换)。
- 联合索引不满足最左前缀原则。
30. Redis 持久化方式?
- RDB:定时快照,恢复快,可能丢失最后一次快照后的数据。
- AOF:记录写命令,数据更安全,文件较大,恢复慢。
- 混合持久化(Redis 4.0+):结合两者优点。
二、Java 集合(15道)
31. ArrayList 扩容机制?
默认初始容量 10,扩容时新容量 = 旧容量 + 旧容量 >> 1(即 1.5 倍)。
32. HashMap 的负载因子为什么是 0.75?
权衡时间和空间。0.75 时,链表长度超过 8 的概率极小,红黑树转换概率低,空间利用率较高。
33. HashMap 和 Hashtable 的区别?
- HashMap 线程不安全,Hashtable 线程安全(方法 synchronized)。
- HashMap 允许 null 键和 null 值,Hashtable 不允许。
- HashMap 迭代器是 fail-fast,Hashtable 不是。
34. ConcurrentHashMap 1.7 和 1.8 的区别?
- JDK 7:分段锁(Segment),锁粒度较粗。
- JDK 8:synchronized + CAS 锁桶(Node),锁粒度更细,并发度更高;链表长度≥8 且数组长度≥64 时转为红黑树。
35. LinkedHashMap 如何实现有序?
继承 HashMap,内部维护一个双向链表,记录插入顺序或访问顺序(accessOrder=true 实现 LRU)。
36. TreeMap 和 HashMap 的区别?
- HashMap:基于哈希表,无序,O(1) 时间复杂度。
- TreeMap:基于红黑树,键有序(自然顺序或 Comparator),O(log n) 时间复杂度。
37. CopyOnWriteArrayList 原理?
写时复制。写操作(add、set、remove)时复制一个新数组,在新数组上操作,完成后将原数组引用指向新数组。读操作无锁,适合读多写少场景。
38. BlockingQueue 常用实现类?
- ArrayBlockingQueue:有界,数组实现。
- LinkedBlockingQueue:可选有界,链表实现。
- PriorityBlockingQueue:无界,支持优先级。
- SynchronousQueue:不存储元素,每个插入操作必须等待另一个线程的移除操作。
39. fail-fast 和 fail-safe 机制?
- fail-fast:快速失败,迭代过程中发现集合被修改(非迭代器自己的 remove 方法),立即抛出 ConcurrentModificationException。如 ArrayList、HashMap。
- fail-safe:安全失败,迭代时先复制原集合,在副本上迭代,不会抛异常。如 CopyOnWriteArrayList、ConcurrentHashMap。
40. Comparable 和 Comparator 的区别?
- Comparable:自然排序,类实现 compareTo() 方法。
- Comparator:定制排序,单独实现 compare() 方法,更灵活。
41. HashSet 如何保证元素不重复?
基于 HashMap 实现,元素作为 HashMap 的 key(value 为固定 Object),利用 HashMap 键的唯一性。
42. Iterator 和 ListIterator 的区别?
- Iterator:可遍历 Set 和 List,只能向后遍历,只能 remove。
- ListIterator:只能遍历 List,可向前向后遍历,可 add、set、remove。
43. Arrays.asList() 的注意事项?
返回的 List 是 Arrays 的内部类 ArrayList(固定大小),不支持 add、remove 操作。若要修改,可 new ArrayList<>(Arrays.asList(...))。
44. Collections.sort() 内部实现?
底层调用 Arrays.sort(),对于对象数组使用 TimSort(归并排序优化),对于基本类型数组使用 Dual-Pivot QuickSort。
45. 如何实现一个 LRU 缓存?
使用 LinkedHashMap(accessOrder=true)或自己实现:双向链表 + HashMap。最近访问的移到链表头部,容量满时淘汰尾部。
三、Java 多线程与并发(20道)
46. 线程的生命周期?
新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、等待(Waiting)、超时等待(Timed Waiting)、终止(Terminated)。
47. 创建线程池的几种方式?
- Executors.newFixedThreadPool(int n):固定大小线程池。
- Executors.newCachedThreadPool():可缓存线程池。
- Executors.newSingleThreadExecutor():单线程线程池。
- Executors.newScheduledThreadPool(int corePoolSize):定时任务线程池。
- 手动 new ThreadPoolExecutor():自定义参数。
48. 线程池的拒绝策略?
- AbortPolicy(默认):直接抛出 RejectedExecutionException。
- CallerRunsPolicy:由调用者线程执行任务。
- DiscardPolicy:直接丢弃任务,不抛异常。
- DiscardOldestPolicy:丢弃队列中最老的任务,然后尝试执行当前任务。
49. synchronized 锁升级过程?
无锁 → 偏向锁(单线程) → 轻量级锁(多线程竞争不激烈) → 重量级锁(竞争激烈)。
50
更多推荐

所有评论(0)