Java面试八股文完整版(高频干货专栏)
bili_12086923676
2026年05月31日 15:04

本文整理Java面试100%高频八股考点,覆盖Java基础、面向对象、集合、多线程、JVM、Spring核心六大核心模块,内容精简、无废话、适配校招/社招面试突击,可直接背诵使用。


一、Java 基础核心八股

1. JDK、JRE、JVM 的区别?

  • JVM(Java虚拟机):Java跨平台的核心,负责运行Java字节码文件.class,不包含编译工具,只负责解析执行程序。

  • JRE(Java运行环境):包含 JVM + Java核心类库,是Java程序运行的必备环境,普通用户只需安装JRE即可运行Java程序。

  • JDK(Java开发工具包):包含 JRE + 编译工具(javac)、调试工具等,是开发者开发Java程序的全套工具。

层级关系:JDK ⊃ JRE ⊃ JVM

2. == 和 equals() 的区别?

  • ==:是运算符

    • 基本数据类型:比较数值是否相等

    • 引用数据类型:比较对象内存地址是否相同

  • equals():是Object类的方法

    • 默认实现:和 == 一致,比较对象地址

    • 重写后(String、Integer等):比较对象内容/数值是否相等

3. String、StringBuilder、StringBuffer 区别?

维度

String

StringBuilder

StringBuffer

可变性

不可变(底层final字符数组)

可变

可变

线程安全

线程安全(不可变)

非线程安全

线程安全(方法加synchronized)

效率

低(频繁拼接会生成新对象)

最高

中等(锁消耗性能)

适用场景

少量字符串定义、不频繁修改

单线程频繁字符串拼接

多线程频繁字符串拼接

4. final、finally、finalize 的区别?

  • final:修饰符

    • 修饰类:类不可被继承

    • 修饰方法:方法不可被重写

    • 修饰变量:变量变为常量,只能赋值一次

  • finally:异常处理关键字,搭配try-catch使用,无论程序是否异常,最终都会执行(唯一不执行场景:System.exit(0)),常用于释放资源。

  • finalize:Object类废弃方法,JVM垃圾回收前会调用该方法,现已被废弃,不推荐使用。

5. 基本数据类型和包装类区别?

  • 基本类型:8种(byte/short/int/long/float/double/char/boolean),存栈内存、无默认null、效率高

  • 包装类:基本类型的对象封装,存堆内存、可null、支持泛型、提供大量工具方法

  • 自动装箱拆箱:JDK5+ 自动转换,装箱:基本类型→包装类;拆箱:包装类→基本类型

  • 缓存机制:Integer等包装类缓存-128~127数值,范围内对象复用,超出则新建对象


二、面向对象OOP核心八股

1. 面向对象四大特性?

  • 封装:隐藏对象内部细节,对外暴露统一访问接口,提高代码安全性、复用性。

  • 继承:子类继承父类属性和方法,实现代码复用,支持单继承、多接口实现。

  • 多态:同一行为不同实现,分为编译多态(重载)、运行多态(重写),提高代码扩展性。

  • 抽象:抽取核心共性,隐藏具体实现,通过抽象类/接口实现,规范代码结构。

2. 重载和重写的区别?

维度

重载(Overload)

重写(Override)

定义

同类中,方法名相同、参数列表不同

子类对父类非final、非private、非static方法重新实现

参数列表

参数个数/类型/顺序必须不同

参数列表必须完全一致

返回值

可任意修改

必须是协变返回(子类类型)

权限

无权限限制

权限不能比父类更严格

多态类型

编译期多态

运行期多态

3. 抽象类和接口的区别?

  • 抽象类(abstract class)

    • 可以有构造方法、成员变量、普通方法、抽象方法

    • 单继承:一个类只能继承一个抽象类

    • 权限:支持public、protected、default权限

    • 核心:模板复用,抽取子类通用代码

  • 接口(interface)

    • JDK8前:只能有常量和抽象方法;JDK8+支持默认方法、静态方法;JDK9+支持私有方法

    • 多实现:一个类可以实现多个接口

    • 权限:默认public

    • 核心:行为规范,定义功能标准


三、Java集合框架高频八股

1. ArrayList 和 LinkedList 区别?

  • 底层结构:ArrayList 基于动态数组;LinkedList 基于双向链表

  • 查询效率:ArrayList 随机查询快(数组下标寻址O(1));LinkedList 只能遍历查询O(n)

  • 增删效率:ArrayList 末尾增删快,中间增删需移动元素;LinkedList 任意位置增删只需修改指针,效率更高

  • 内存占用:ArrayList 存在数组扩容冗余空间;LinkedList 每个节点保存前后指针,占用内存更多

  • 线程安全:两者均非线程安全

2. HashMap 底层原理(核心必背)

HashMap 是基于数组+链表+红黑树实现的键值对存储结构,无序、key唯一、允许null键null值、非线程安全。

存储流程:

  1. 根据key计算hash值,通过哈希算法定位数组下标

  2. 若下标位置无元素,直接插入

  3. 若有元素,发生哈希冲突:

    1. 链表长度 < 8:采用拉链法,链表尾部插入节点

    2. 链表长度 ≥8 且 数组容量≥64:链表转换为红黑树,提升查询效率

    3. 链表长度 ≤6:红黑树退化为链表

  4. 当元素数量超过负载因子(0.75)*容量,触发数组扩容(扩容为原容量2倍)

3. HashMap JDK1.7 和 JDK1.8 核心区别?

  • 底层结构:1.7 数组+单向链表;1.8 数组+单向链表+红黑树

  • 插入方式:1.7 头插法(多线程易出现环形链表死循环);1.8 尾插法

  • 哈希扰动:1.8 优化hash算法,减少哈希冲突

  • 扩容机制:1.8 优化扩容迁移逻辑,效率更高

4. ConcurrentHashMap 如何保证线程安全?

  • JDK1.7:分段锁机制,将数组分为16个Segment,每个Segment独立加锁,并发度高

  • JDK1.8:CAS + synchronized 实现并发安全,锁粒度细化到数组单个节点

    • 无冲突时:CAS无锁插入

    • 有冲突时:对链表/红黑树头节点加synchronized锁

  • 相比HashTable全局锁,并发性能大幅提升


四、多线程与并发核心八股

1. 进程和线程的区别?

  • 进程:资源分配的最小单位,独立占用内存、CPU资源,进程间相互隔离,开销大

  • 线程:CPU调度的最小单位,隶属于进程,共享进程资源,开销小、切换快

  • 关系:一个进程至少包含一个线程,多线程可提升程序并发执行效率

2. sleep() 和 wait() 的区别?

  • 归属类:sleep() 是Thread类方法;wait() 是Object类方法

  • 锁释放:sleep() 不释放锁;wait() 释放锁

  • 唤醒方式:sleep() 时间到自动唤醒;wait() 需被notify()/notifyAll()唤醒

  • 适用场景:sleep() 线程休眠;wait() 线程间通信

3. synchronized 和 Lock 的区别?

维度

synchronized

Lock(ReentrantLock)

底层

JVM原生锁,隐式锁

JDK代码实现,显式锁

锁释放

自动释放(代码执行完/异常)

必须手动unlock()释放

锁特性

可重入、不可中断、非公平

可重入、可中断、可公平/非公平

功能

功能单一

支持限时锁、条件锁,功能丰富

4. volatile 关键字作用?

volatile 是轻量级同步关键字,核心两大作用:

  1. 保证可见性:线程修改变量后,立即刷新到主内存,其他线程可实时感知最新值

  2. 禁止指令重排:避免CPU指令优化重排,解决单例模式DCL双重检查锁漏洞

⚠️ 不保证原子性:无法保证复合操作(i++)的线程安全,需配合锁使用

5. 线程池核心参数?

核心7大参数(ThreadPoolExecutor):

  1. 核心线程数corePoolSize:常驻线程数,即使空闲也不会回收

  2. 最大线程数maximumPoolSize:线程池允许的最大线程总数

  3. 空闲时间keepAliveTime:非核心线程空闲超时时间,超时被回收

  4. 时间单位unit:空闲时间单位

  5. 阻塞队列workQueue:存储等待执行的任务

  6. 线程工厂threadFactory:创建线程的工厂,可自定义线程名称、优先级

  7. 拒绝策略handler:任务爆满时的处理策略(4种默认策略)


五、JVM核心面试八股

1. JVM 内存区域划分?

JVM运行时数据区分为线程私有区线程共享区

  • 线程私有(随线程创建/销毁)

    • 程序计数器:记录当前线程执行字节码行号,唯一无OOM区域

    • 虚拟机栈:存储局部变量、方法栈帧,方法执行入栈,结束出栈

    • 本地方法栈:服务于native本地方法

  • 线程共享(随JVM启动/关闭)

    • 堆内存:存储所有对象实例、数组,GC主要回收区域

    • 方法区(元空间):存储类信息、常量、静态变量、即时编译代码

2. GC 垃圾回收机制?哪些对象可回收?

JVM GC 主要回收堆内存中无引用的对象,回收时机:内存不足、主动调用GC、定时回收。

对象存活判断:

  • 引用计数法:对象引用数为0则回收(无法解决循环引用,JVM未采用)

  • 可达性分析算法(JVM主流):以GC Roots为起点,不可到达的对象判定为垃圾对象

GC Roots 包含:

虚拟机栈局部变量对象、本地方法栈引用对象、方法区静态变量/常量引用对象

3. 双亲委派模型?

JVM类加载机制的核心规则:子类加载器收到加载请求,先向上委托父类加载器加载,父类无法加载再由子类加载

加载器层级:

启动类加载器 > 扩展类加载器 > 应用程序类加载器 > 自定义加载器

核心作用:

  1. 保证核心类安全,防止自定义类覆盖JDK核心类(如java.lang.String)

  2. 实现类的全局唯一性


六、Spring 核心八股

1. IOC 控制反转原理?

传统开发:开发者主动new对象,主动创建依赖关系,控制权在程序员。

IOC控制反转:将对象创建、依赖注入的控制权交给Spring容器,程序被动接收对象,实现解耦

核心实现:Bean工厂 + 反射机制

2. AOP 面向切面编程原理?

AOP 是在不修改原有业务代码的前提下,对方法进行增强,实现业务代码与通用日志、事务、权限等横切逻辑解耦

核心原理:动态代理

  • 目标类有接口:JDK动态代理

  • 目标类无接口:CGLIB动态代理(继承子类重写方法)

3. Spring Bean 生命周期?

完整流程:实例化 → 属性填充 → 初始化 → 销毁

  1. Bean实例化:Spring通过反射创建Bean对象

  2. 属性填充:自动装配依赖属性(DI注入)

  3. 初始化前置处理:BeanPostProcessor前置处理

  4. 初始化:执行InitializingBean、自定义init方法

  5. 初始化后置处理:BeanPostProcessor后置处理

  6. Bean就绪:放入单例池,供业务调用

  7. 销毁:容器关闭时,执行DisposableBean、自定义destroy方法

4. Spring Bean 作用域?

  • singleton(默认):单例,整个Spring容器仅一个Bean实例

  • prototype:多例,每次获取Bean都会新建实例

  • request:每次HTTP请求创建一个Bean

  • session:每个浏览器会话创建一个Bean


七、专栏总结

本文覆盖Java面试90%以上基础核心八股,所有考点均为大厂校招、社招高频提问点。建议优先背诵集合、多线程、JVM、Spring四大难点模块,基础模块熟记核心区别即可,面试时可结合场景灵活作答。