Java 校招必备八股文
Java 校招面试里,真正高频的内容其实很集中。你不需要一上来把所有框架源码都啃完,先把基础八股打牢,已经能覆盖大部分一面、二面的提问范围。通常会围绕这几块展开:Java 基础、集合、并发、JVM、数据库、Spring、MySQL、Redis、网络。
这篇文章按校招常考思路来写,尽量讲清“是什么、为什么、怎么考”。
一、Java 基础
Java 为什么跨平台?
因为 Java 代码先编译成字节码,运行时由 JVM 解释或编译执行。不同平台安装不同的 JVM,就能实现“一次编写,到处运行”。
JDK、JRE、JVM 的区别:
- JVM 是 Java 虚拟机,负责运行字节码。
- JRE 是 Java 运行环境,包含 JVM 和基础类库。
- JDK 是开发工具包,包含 JRE 以及编译、调试等工具。
== 和 equals() 的区别:
==比较的是基本类型的值,或引用类型的地址。equals()默认也是比较地址,但很多类比如String重写后比较的是内容。
hashCode() 和 equals() 的关系:
- 如果两个对象
equals()为true,那么它们的hashCode()必须相等。 hashCode()相等,不一定equals()为true。
为什么要同时重写?
因为哈希容器如 HashMap、HashSet 会先用 hashCode() 找桶,再用 equals() 判断是不是同一个对象。
String、StringBuilder、StringBuffer 的区别:
String不可变。StringBuilder可变,线程不安全,但效率高。StringBuffer可变,线程安全,但效率略低。
为什么 String 不可变?
- 便于缓存哈希值。
- 更安全,适合作为常量和键。
- 适合字符串常量池复用。
重载和重写的区别:
- 重载:同一个类中,方法名相同,参数列表不同。
- 重写:子类对父类方法重新实现,方法名和参数基本一致。
更多全面的java大厂面试题和必备八股文都收录在专栏里面了:
https://www.nowcoder.com/creation/manager/columnDetail/0n9XOd
二、面向对象三大特性
封装:
把属性和方法放在类里,对外隐藏实现细节。
继承:
子类继承父类,复用父类已有能力。
多态:
同一个父类引用,指向不同子类对象,调用同一个方法会表现出不同结果。
多态的前提:
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
三、集合高频
Java 集合主要分两大类:
CollectionMap
List、Set、Map 的区别:
List有序,可重复。Set无序或有序,不可重复。Map存键值对,key 不可重复。
ArrayList 和 LinkedList 区别:
ArrayList底层是动态数组,查询快,尾插效率高。LinkedList底层是双向链表,插入删除方便,但查询慢。
校招面试常见回答:
- 随机访问多,用
ArrayList - 中间插删多,用
LinkedList - 实际开发中
ArrayList更常用
HashMap 底层原理:
JDK 1.8 中,HashMap 底层是“数组 + 链表 + 红黑树”。
存储过程:
- 先根据 key 的
hashCode()计算哈希值 - 定位到数组下标
- 如果该位置为空,直接插入
- 如果发生哈希冲突,放入链表或红黑树中
为什么 JDK 1.8 要引入红黑树?
因为链表过长时,查询效率会退化到 O(n),转成红黑树后可以优化到 O(logn)。
HashMap 和 Hashtable 的区别:
HashMap线程不安全,效率高。Hashtable线程安全,但基本已经很少用了。HashMap允许null键和null值,Hashtable不允许。
HashSet 为什么不能重复?
因为底层是基于 HashMap 实现的,元素作为 key 存储。插入时先比较 hashCode(),再比较 equals(),相同则认为重复。
ConcurrentHashMap 为什么线程安全?
JDK 1.7 用分段锁。JDK 1.8 主要用 CAS + synchronized,锁粒度更细,并发性能更好。
四、并发编程高频
线程和进程的区别:
- 进程是资源分配的基本单位。
- 线程是 CPU 调度的基本单位。
- 一个进程可以有多个线程,线程共享进程资源。
创建线程的方式:
- 继承
Thread - 实现
Runnable - 实现
Callable - 线程池创建
为什么更推荐线程池?
- 减少线程频繁创建和销毁的开销
- 更方便统一管理线程
- 能控制并发数量,提高稳定性
synchronized 和 Lock 的区别:
synchronized是 Java 关键字,使用简单,自动释放锁。Lock是接口,功能更灵活,比如可中断、可超时、公平锁等。- 复杂并发控制通常更适合
Lock。
volatile 的作用:
- 保证可见性
- 禁止指令重排
- 不保证原子性
为什么 i++ 不是线程安全的?
因为它不是原子操作,本质上分为读取、加一、写回三步,多线程下可能发生竞争。
CAS 是什么?
CAS 即 Compare And Swap,比较并交换。它是一种无锁原子操作,常用于实现原子类和并发容器。
AQS 是什么?
AQS 即 AbstractQueuedSynchronizer,是很多同步器的基础框架,比如:
ReentrantLockCountDownLatchSemaphoreReentrantReadWriteLock
线程池核心参数:
corePoolSize:核心线程数maximumPoolSize:最大线程数keepAliveTime:非核心线程空闲存活时间workQueue:任务队列threadFactory:线程工厂handler:拒绝策略
线程池执行流程很常考:
- 线程数小于核心线程数,创建核心线程执行任务
- 否则放入阻塞队列
- 队列满了且线程数小于最大线程数,创建非核心线程
- 还满了就执行拒绝策略
常见拒绝策略:
- 直接抛异常
- 调用者自己执行
- 丢弃当前任务
- 丢弃最旧任务
五、JVM 必考
JVM 内存区域:
- 程序计数器
- Java 虚拟机栈
- 本地方法栈
- 堆
- 方法区
堆中主要放对象实例,栈中主要放局部变量、方法调用信息。
为什么会栈溢出?
递归太深或者局部变量过大,导致栈空间不够。
为什么会堆溢出?
创建对象太多,堆空间不够,且垃圾回收后仍无法释放足够内存。
类加载过程:
- 加载
- 验证
- 准备
- 解析
- 初始化
双亲委派模型:
一个类加载器接到类加载请求后,会先委托父加载器去加载,父加载器加载不了,自己再加载。
好处:
- 防止类重复加载
- 保证核心类库安全
垃圾回收主要回收哪里?
主要回收堆和方法区中的无用对象。
如何判断对象是否可回收?
主流思路是可达性分析。若对象和 GC Roots 没有引用链相连,则可认为可回收。
常见垃圾回收算法:
- 标记清除
- 标记整理
- 复制算法
- 分代收集
为什么要分代?
因为不同对象生命周期不同:
- 新生代对象大多朝生夕死,适合复制算法
- 老年代对象存活率高,适合标记清除或标记整理
常见垃圾收集器:
- Serial
- ParNew
- CMS
- G1
校招里一般说清 CMS 和 G1 就够了。
CMS:
- 以获取最短停顿时间为目标
- 会有内存碎片问题
G1:
- 面向服务端
- 将堆分成多个 Region
- 可预测停顿时间
- 适合大内存场景
六、MySQL 高频
事务四大特性 ACID:
- 原子性
- 一致性
- 隔离性
- 持久性
事务并发问题:
- 脏读
- 不可重复读
- 幻读
MySQL 四种隔离级别:
- 读未提交
- 读已提交
- 可重复读
- 串行化
MySQL 默认隔离级别:
Repeatable Read,可重复读
为什么会有幻读?
同一个事务里前后两次范围查询,第二次查到了第一次没有的行,像“幻觉”一样。
索引是什么?
索引是帮助数据库快速查找数据的数据结构,MySQL InnoDB 常用 B+ 树索引。
为什么不用红黑树而用 B+ 树?
- B+ 树更适合磁盘 IO
- 高度更低
- 范围查询效率高
- 叶子节点天然有序,便于区间查询
聚簇索引和非聚簇索引:
- 聚簇索引:数据和索引放在一起,InnoDB 主键索引就是聚簇索引
- 非聚簇索引:索引和数据分开存,需要回表
什么是回表?
通过二级索引找到主键后,再去主键索引中查完整数据。
什么情况会导致索引失效?
- 对索引列使用函数
- 隐式类型转换
- 最左前缀不满足
like以%开头- 使用
or且某些字段无索引
七、Redis 高频
Redis 为什么快?
- 基于内存
- 单线程模型避免线程切换开销
- IO 多路复用
- 数据结构高效
Redis 常见数据类型:
StringHashListSetZSet
应用场景:
String:缓存、计数器Hash:对象属性存储List:消息队列、列表Set:去重、共同好友ZSet:排行榜、延迟队列
缓存穿透、击穿、雪崩:
缓存穿透:
- 查询不存在的数据,请求直接打到数据库
解决:
- 缓存空值
- 布隆过滤器
缓存击穿:
- 某个热点 key 突然失效,大量请求打到数据库
解决:
- 热点 key 永不过期
- 加互斥锁
缓存雪崩:
- 大量 key 同时过期,大量请求涌向数据库
解决:
- 过期时间加随机值
- 多级缓存
- 限流降级
Redis 持久化:
- RDB:快照
- AOF:追加日志
区别:
- RDB 恢复快,但可能丢失最后一次快照后的数据
- AOF 更安全,但文件更大,恢复较慢
八、Spring 高频
Spring 的核心是什么?
最核心是:
- IOC
- AOP
IOC 是什么?
IOC 即控制反转,把对象创建和依赖管理交给 Spring 容器,而不是自己 new。
DI 是什么?
DI 即依赖注入,是 IOC 的具体实现方式。
AOP 是什么?
AOP 即面向切面编程,在不修改业务代码的前提下,统一处理日志、事务、权限等横切逻辑。
Spring Bean 的生命周期简版:
- 实例化
- 属性注入
- 调用各种感知接口
- 执行初始化方法
- 使用 Bean
- 容器关闭时执行销毁方法
Spring 事务失效场景是高频题:
- 方法不是
public - 自调用导致代理失效
- 异常被吃掉
- 数据库引擎不支持事务
- 没有被 Spring 管理
Spring Boot 为什么方便?
因为它提供了:
- 自动配置
- 起步依赖
- 内嵌 Tomcat
- 简化配置和开发流程
九、网络八股
TCP 和 UDP 的区别:
- TCP 面向连接,可靠传输
- UDP 无连接,不保证可靠性,但更快
TCP 为什么可靠?
- 三次握手建立连接
- 序号机制
- 确认应答
- 超时重传
- 滑动窗口
- 流量控制
- 拥塞控制
为什么三次握手不是两次?
因为三次握手可以让双方都确认“自己能发、也能收”,从而保证连接建立是可靠的。
为什么四次挥手?
因为 TCP 是全双工,双方都要单独关闭发送通道,所以通常需要四次。
HTTP 和 HTTPS 区别:
- HTTP 明文传输,不安全
- HTTPS = HTTP + SSL/TLS,加密传输,更安全
Session 和 Cookie 的区别:
- Cookie 存在客户端
- Session 存在服务端
- Session 通常依赖 Cookie 中的 SessionId 进行识别
十、校招面试怎么背最有效
如果你时间有限,优先按这个顺序准备:
- Java 基础
- 集合
- 并发
- JVM
- MySQL
- Redis
- Spring
因为这几块几乎是 Java 校招的主战场。
建议你背八股时,不要只背定义,要用“三段式”回答:
- 先说结论
- 再说原理
- 最后补应用场景或对比
比如问 “HashMap 为什么线程不安全?”
可以这么答:
先说结论,HashMap 是线程不安全的,多线程下可能出现数据覆盖、读取异常等问题。然后说原因,因为它内部没有加锁,多个线程同时 put 或扩容时会竞争共享数据。最后补一句,如果并发场景下需要线程安全,一般用 ConcurrentHashMap。
这样回答会比只说一句“因为没加锁”好很多。
十一、最后的速记版
Java 校招最该背住的几个点:
==比地址,equals()比内容HashMap底层是数组 + 链表 + 红黑树ArrayList底层是动态数组volatile保证可见性,不保证原子性- 线程池比手动创建线程更推荐
- JVM 重点是内存区域、类加载、GC
- MySQL 索引用 B+ 树
- Redis 快是因为内存 + 单线程 + IO 多路复用
- Spring 核心是 IOC 和 AOP
- TCP 可靠,UDP 快
如果这些主干你能讲顺,再配合项目经历,已经足够应对大多数校招面试。
查看12道真题和解析