简介:这份 Java 初级面试题汇总文档面向刚从学校毕业或培训结业的 Java 求职者,帮助其在面试前系统梳理高频考点、查漏补缺。内容按十八个模块组织,覆盖 Java 基础、多线程、反射、对象拷贝、JavaWeb、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/SpringCloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM,共收录 208 道题目并附参考答案。基础部分对 JDK 与 JRE 的区别、== 与 equals 的差异、hashCode 与 equals 的关系、final 关键字作用等均有代码示例与逐行解读,便于理解而非死记。资源包为单个 docx 文件,大小约 155KB,轻量易携带,可打印或导入笔记软件随时复习。目前已有 623 人学习,适合作为初级岗位面试前的清单式自测材料,按模块逐项过题即可定位薄弱环节。
1. 初级 Java 面试到底考什么:208 道题里藏着三条得分主线
很多人准备 Java 初级面试,第一反应是去背“八股文”,结果背了一堆 JDK 和 JRE 的区别,面试官却问了一句“你项目里线程池参数怎么设的”,当场卡壳。这份 208 道题的清单之所以值得拿来当主线,是因为它把十八个模块的考点摊开给你看:Java 基础、多线程、集合、Spring 全家桶、MySQL、Redis、JVM,一个不落。初级岗的面试逻辑其实很朴素——先确认你语言底子不虚,再确认你用过框架、碰过数据库,最后看你有没有踩过坑、能不能把坑讲明白。分值分布上,Java 基础和集合通常占问答量的一半以上,多线程和 JVM 是拉开差距的地方,框架和中间件则决定你能不能进到二面。这份清单适合刚出学校或刚培训完、需要一份能直接背能直接练的题目底稿的人。下面按“考点分布—高频题怎么答—易错点—押题思路”推下去,每道题都给答题骨架,不给你泛泛的概念。
2. Java 基础与集合:高频题占一半,答题要带代码和边界
2.1 基础题的三类问法与答题骨架
初级面试的基础题基本跑不出三类:概念辨析、行为验证、边界陷阱。概念辨析比如“JDK 和 JRE 有什么区别”,答题骨架是“定义 + 包含关系 + 使用场景”三句话:JDK 是开发工具包,包含 JRE 和编译器 javac 及调试分析工具;JRE 只是运行环境;所以只运行装 JRE,要写代码装 JDK。三句话说完就停,不要展开成一段散文。
行为验证类比如“== 和 equals 的区别”,面试官最想听的是你分得清基本类型和引用类型。答题时先给结论再给代码:
String x = "string"; String y = "string"; String z = new String("string"); System.out.println(x == y); // true,常量池同一引用 System.out.println(x == z); // false,new 在堆上新开空间 System.out.println(x.equals(z)); // true,String 重写了 equals 做值比较这段代码的价值在于它同时覆盖了常量池、堆内存和 equals 重写三个点。讲完代码补一句:equals 在 Object 里本质就是this == obj,是 String、Integer 这些类重写后才变成值比较,自定义类不重写就还是引用比较。这一句是区分“背过”和“懂了”的分水岭。
边界陷阱类最典型的是“两个对象 hashCode 相同,equals 一定为 true 吗”。答案是错,反例是“通话”和“重地”两个字符串哈希值相同但内容不同。答题时把哈希表原理带一句:哈希值相等只说明落在同一个桶,桶内还要靠 equals 逐个比,所以哈希冲突不等于对象相等。这类题面试官不是要你背结论,是要你证明自己知道哈希表怎么工作。
2.2 集合题必须落到数据结构和线程安全
集合是初级面试的重灾区,因为这里既能问概念又能问源码还能问并发。高频题集中在四组对比:ArrayList 与 LinkedList、HashMap 与 Hashtable、ArrayList 与 Vector、Collection 与 Collections。
答 ArrayList 与 LinkedList,别只说“一个数组一个链表”,要落到操作代价上:ArrayList 随机访问 O(1),非尾部增删要移动元素;LinkedList 随机访问要遍历指针,头尾增删快。然后给一句选型结论:读多用 ArrayList,增删多用 LinkedList。面试官接着常追问“那 LinkedList 做队列行不行”,你可以答它实现了 Deque,可以当双端队列用,但真要高并发还是用并发包里的队列。
答 HashMap 与 Hashtable,三个维度一次说完:null 支持(HashMap 允许一个 null key 和多个 null value,Hashtable 不允许)、线程安全(Hashtable 方法加 synchronized,HashMap 不安全)、替代方案(单线程用 HashMap,多线程用 ConcurrentHashMap,Hashtable 是保留类不推荐)。这里有个容易加分的点:主动提一句 HashMap 在 JDK 8 里哈希冲突多了会从链表转红黑树,把查找从 O(n) 降到 O(log n),说明你看过实现而不只是背结论。
线程安全集合那道题,标准答法是列举 Vector、Hashtable、Stack 是老的同步类,然后补一句“现在更推荐 java.util.concurrent 下的 ConcurrentHashMap、CopyOnWriteArrayList”。面试官问这题的真实意图是看你知不知道老类和并发包的取舍,只背三个名字拿不到满分。
2.3 真题演练:从“会不会”到“讲得清”
拿清单里第 23 题“说一下 HashMap 的实现原理”做示范。这题是初级面试的分水岭题,答得好直接建立信任。答题分四层:第一层说结构,数组加链表,JDK 8 起冲突多时转红黑树;第二层说 put 流程,key 的 hashCode 经过扰动函数算出下标,桶空就放,不空就比较,相同就覆盖,不同就挂链或进树;第三层说扩容,默认容量 16、负载因子 0.75,超过阈值翻倍扩容并重新分布;第四层说线程安全,HashMap 并发 put 可能丢数据,多线程换 ConcurrentHashMap。四层讲完控制在两分钟内,每层一句到两句,不要陷进源码细节。
再拿第 34 题“怎么确保一个集合不能被修改”练手。答题先给方法再给代码再给异常类型:
List<String> list = new ArrayList<>(); list.add("x"); Collection<String> readOnly = Collections.unmodifiableCollection(list); readOnly.add("y"); // 抛 UnsupportedOperationException讲解时点明这是“视图”不是“拷贝”,原集合改了只读视图也会跟着变,所以它防的是通过视图修改,不防原集合被改。这个细节说出来,面试官会认为你不是照抄 API 文档。
提示:基础与集合模块的题,答题统一走“结论一句 + 代码或对比一句 + 边界一句”的三段式,超过三段的展开留给面试官追问,主动展开容易把自己带进不熟的源码里。
3. 多线程与 JVM:拉开差距的模块,答原理要答到“为什么这么设计”
3.1 线程基础:状态、创建方式与 sleep/wait
多线程模块在初级面试里出现频率仅次于基础,但深度要求不高,考的是你有没有把概念理清。线程状态那题,六个状态 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED 要能按顺序说,并且能举一个进入条件:调 start 进 RUNNABLE,抢不到 synchronized 进 BLOCKED,调 wait 进 WAITING,调 sleep 进 TIMED_WAITING。能举条件就说明不是死背。
创建线程三种方式:继承 Thread、实现 Runnable、实现 Callable。答题时补一句取舍:实际开发推荐实现接口,因为 Java 单继承,实现接口还能保留继承其他类的余地;需要返回值就用 Callable 配 FutureTask。Runnable 和 Callable 的区别一句话:前者无返回值不能抛受检异常,后者有返回值且能抛。
sleep 和 wait 的区别是必考题,按四个维度答:所属类(Thread 对 Object)、是否释放锁(sleep 不释放,wait 释放)、唤醒方式(sleep 到时自醒,wait 要 notify/notifyAll)、使用前提(wait 必须在 synchronized 块里)。四个维度答全,这题就是满分答案。
3.2 线程池:七种创建方式背后的一个核心类
线程池是初级面试里最容易被追问到翻车的点。清单里第 44 题列了七种创建方式,答题策略是先说“七种里前六种都是对 ThreadPoolExecutor 的封装”,然后挑三个讲清楚:newFixedThreadPool 固定线程数配无界队列,任务堆积有内存风险;newCachedThreadPool 用 SynchronousQueue,空闲 60 秒回收,适合大量短任务;newScheduledThreadPool 支持定时和周期调度。最后落到核心参数:核心线程数、最大线程数、空闲存活时间、工作队列、拒绝策略。
面试官常追问“线程池任务提交后怎么走”,答题顺序是:核心线程没满就建核心线程,满了进队列,队列满了且没到最大线程数就建非核心线程,再满就触发拒绝策略。这个流程能画在纸上讲最好,讲的时候强调“先队列后扩容”这个顺序,很多人记反。
submit 和 execute 的区别是送分题:execute 只接 Runnable 无返回值,submit 接 Runnable 和 Callable 返回 Future,异常处理也不同——submit 把异常包在 Future 里,不调 get 就看不到。这一点说出来,面试官会追一句“那线上怎么发现线程池里的异常”,你可以答自定义 ThreadFactory 设 UncaughtExceptionHandler 或者统一在任务里 try-catch。
3.3 锁与并发安全:synchronized 升级和 volatile 边界
synchronized 锁升级是初级面试里的“超纲边缘题”,答得好是加分项。答题主线:对象头里有 Mark Word,偏向锁记录线程 ID,同一线程再进来直接放行;有竞争就升级轻量级锁,靠 CAS 自旋抢;自旋失败再升级重量级锁,走操作系统互斥量。最后补一句设计意图:升级是为了在无竞争和低竞争场景下避免重量级锁的系统调用开销。
volatile 和 synchronized 的区别按三点答:修饰对象(变量对类/方法/代码块)、保证范围(volatile 只保证可见性和有序性不保证原子性,synchronized 三者都保证)、阻塞行为(volatile 不阻塞,synchronized 可能阻塞)。然后主动给一个反例:i++用 volatile 修饰仍然不安全,因为读改写三步不是原子的,要原子性得用 AtomicInteger 或加锁。这个反例是面试官最想听到的“你真的用过”。
防止死锁那题,答题给四条:用带超时的 tryLock、用并发包现成类、降低锁粒度、缩小同步块。每条配一句场景,比如“两个账户转账按账户 ID 排序加锁”就是降低死锁概率的经典做法。
3.4 真题演练:JVM 内存与 GC 的初级答法
初级岗问 JVM 不会太深,高频是“JVM 内存区域”和“对象什么时候被回收”。内存区域答题按线程私有和共享分:私有的是程序计数器、虚拟机栈、本地方法栈;共享的是堆和方法区(JDK 8 后叫元空间)。堆再分新生代和老年代,新生代分 Eden 和两个 Survivor。分区讲完补一句各区域会抛什么异常:栈溢出 StackOverflowError,堆溢出 OutOfMemoryError。
GC 那题答两点就够:怎么判断对象死了——可达性分析,从 GC Roots 出发找不到就是可回收;什么时候回收——新生代 Minor GC 频繁但快,老年代 Full GC 慢且会停顿。能补一句“大对象直接进老年代、长期存活对象晋升老年代”就更好。初级面试不要求你讲 G1 的 Region,但你要能说出“新生代用复制算法、老年代用标记清除或标记整理”这个对应关系。
注意:多线程和 JVM 的题,面试官最怕听到“背课文式”的长篇。每答完一个点停半秒,看面试官反应,他点头你再往下,他追问说明他想听细节,这时候再展开源码层面的东西。
4. 框架与中间件:Spring、MySQL、Redis 的初级考法
4.1 Spring 与 Spring Boot:IOC、AOP 和自动配置
Spring 在初级面试里几乎必问,核心就两个词:IOC 和 AOP。IOC 答题说“控制反转,对象的创建和依赖注入交给容器”,然后举一个具体场景:Service 里注入 Dao 不用自己 new,容器启动时装配好。AOP 答题说“面向切面,把日志、事务这类横切逻辑从业务代码里抽出来”,然后说实现方式:JDK 动态代理要求目标类实现接口,CGLIB 通过继承生成子类,Spring 默认有接口用 JDK 代理、没接口用 CGLIB。
Spring Boot 的高频题是“自动配置原理”,初级答法不用陷进源码:约定大于配置,启动类上的注解开启自动配置,框架根据类路径里的依赖和配置文件决定装配哪些 Bean,比如引入 web 依赖就自动配好内嵌容器。再补一句 starter 的作用:把一组依赖打包,引入一个 starter 等于引入一套功能。这个答法足够应付初级岗,面试官追问源码你再往条件注解上引。
Bean 的作用域和生命周期也是常考点。作用域答 singleton 和 prototype 两个主要的,singleton 是容器内唯一、prototype 是每次获取新建。生命周期按“实例化—属性注入—初始化前后—使用—销毁”讲,能说出初始化前后有扩展点就行,不用背全部接口名。
4.2 MySQL 与 Redis:索引、事务、缓存三件套
MySQL 初级面试集中在索引和事务。索引那题答:索引是加快查询的数据结构,InnoDB 用 B+ 树,因为非叶子节点只存键、叶子节点存数据且用链表相连,所以范围查询和磁盘 IO 都友好。然后给一条实战结论:给 where、order by 常用列建索引,但索引不是越多越好,写操作要维护索引。面试官常追问“什么情况索引失效”,答最左前缀不满足、对索引列做函数运算、隐式类型转换、以通配符开头的 like,四条足够。
事务那题答 ACID 四个特性各一句,然后落到隔离级别:读未提交、读已提交、可重复读、串行化,MySQL 默认可重复读。再补一句可重复读靠 MVCC 加间隙锁减少幻读,这个点说出来比只背四个级别高一档。
Redis 初级考法集中在“为什么快”和“缓存三大问题”。为什么快答三点:纯内存操作、单线程避免锁竞争和上下文切换、IO 多路复用。缓存三大问题答:穿透是查不存在的数据打到库,用布隆过滤器或空值缓存;击穿是热点 key 过期瞬间打库,用互斥锁或逻辑过期;雪崩是大量 key 同时过期,给过期时间加随机值。每个问题配一个解法,答完就停。
4.3 消息队列与注册中心:RabbitMQ、Kafka、Zookeeper 的定位题
这三个中间件在初级面试里多是定位题,考你知不知道它们是干什么的、什么时候用。RabbitMQ 答:消息 broker,支持灵活路由,适合业务解耦、异步、削峰,要提消息确认和持久化保证不丢。Kafka 答:高吞吐分布式消息系统,按分区顺序写磁盘,适合日志收集和流式处理,消费端靠 offset 记录位置。Zookeeper 答:分布式协调,提供选主、配置管理、分布式锁,Kafka 早期依赖它管元数据。
答题时把三者放一起对比一句:RabbitMQ 重路由灵活,Kafka 重吞吐,Zookeeper 不是消息队列是协调服务。这一句能防止面试官把概念混着问时你答串。
4.4 真题演练:MyBatis 与 Hibernate 的取舍题
“MyBatis 和 Hibernate 有什么区别”是框架模块的经典对比题。答题按四点:SQL 控制(MyBatis 手写 SQL 灵活,Hibernate 自动生成 SQL 屏蔽数据库差异)、映射方式(MyBatis 靠 XML 或注解映射结果集,Hibernate 靠对象关系映射)、学习成本(MyBatis 上手快但要自己管 SQL,Hibernate 体系大)、适用场景(复杂查询和 SQL 优化多用 MyBatis,领域模型稳定、CRUD 为主可用 Hibernate)。最后给一句个人倾向:国内互联网项目 MyBatis 更常见,因为 SQL 可控可优化。这句不是站队,是告诉面试官你知道实际项目怎么选。
MyBatis 的#{}和${}区别也是高频题:前者预编译用占位符,防 SQL 注入;后者字符串拼接,有注入风险,只用在表名、列名这类不能预编译的地方。答完补一句“能预编译就别用拼接”,态度分就有了。
5. 易错点:这五类题最容易把背过的答案答翻车
5.1 错在把 equals 和 hashCode 的契约说反
错在哪:被问“hashCode 相同 equals 是否一定 true”时答“是”。为什么错:把哈希冲突和对象相等混为一谈,哈希值相同只代表落在同一个桶。怎么答对:先答“不一定”,再给“通话”和“重地”哈希相同的反例,最后补契约——equals 相等则 hashCode 必须相等,反之不成立。答题时把契约方向说清楚,比背结论更能拿分。
5.2 错在把线程池的扩容顺序记反
错在哪:答“核心线程满了直接建非核心线程,再满进队列”。为什么错:实际是先核心、再队列、队列满才扩到最大线程数,顺序反了会导致对拒绝策略触发时机的判断全错。怎么答对:按“核心线程—工作队列—最大线程—拒绝策略”四步说,并补一句“所以用无界队列的线程池最大线程数参数形同虚设”,这句能证明你理解参数之间的联动。
5.3 错在把 String 的不可变和 StringBuilder 的线程安全混着说
错在哪:答“StringBuilder 线程安全所以性能低”。为什么错:StringBuilder 恰恰是非线程安全的,线程安全的是 StringBuffer,性能关系也因此反过来。怎么答对:三件套一次说清——String 不可变每次操作产生新对象,StringBuffer 可变且方法加同步,StringBuilder 可变不同步所以单线程更快。再补一句选型:频繁拼接单线程用 StringBuilder,多线程用 StringBuffer,少量拼接直接用 String。
5.4 错在把索引失效的原因答成“索引没用上就是失效”
错在哪:只背“索引会失效”却说不出触发条件。为什么错:面试官问的是排查能力,不是结论。怎么答对:列四条具体触发条件——不满足最左前缀、索引列参与函数或运算、隐式类型转换、like 以通配符开头,每条配一个 SQL 例子。最后补一句排查手段:用 explain 看执行计划里的 type 和 key 字段,type 出现 ALL 就是全表扫。
5.5 错在把 sleep 和 wait 的锁行为说反
错在哪:答“sleep 会释放锁,wait 不释放”。为什么错:正好相反,wait 释放锁是为了让别的线程进来唤醒它,sleep 抱着锁睡。怎么答对:按所属类、是否释放锁、唤醒方式、使用前提四维答,并补一句“wait 不释放锁的话 notify 永远等不到锁,逻辑就死循环了”,用因果把结论锁死,比干背更难忘。
6. 押题思路:把 208 道题压成一张两分钟答题卡
临考阶段最忌讳从头到尾再刷一遍题。我的做法是把清单按“必答、会答、能聊”三档重排:必答是基础、集合、多线程里那些每年都出现的题,要求两分钟内讲完且带一个代码或对比;会答是 Spring、MySQL、Redis 的核心题,要求一分钟内给出结论加一个场景;能聊是 JVM、消息队列、Zookeeper 的定位题,要求三十秒说清是什么、什么时候用。三档之外的全部放弃,初级岗不会因为你答不出 Kafka 分区副本机制就挂你,但会因为你说不清 HashMap 扩容而挂你。
每道必答题我都强制走一个固定动作:先说结论,再给证据,最后留钩子。拿“ArrayList 和 LinkedList 区别”举例,结论是读多用前者、增删多用后者;证据是数组随机访问 O(1)、链表要遍历;钩子是“不过实际项目里 ArrayList 用得更多,因为尾部追加也是均摊 O(1),而且缓存友好”。钩子的作用是引导面试官往你熟的方向追问,而不是让他自由发挥问到你不会的地方。
下面这张表是我自己押题时用的优先级模板,按模块给权重,你可以照着自己的薄弱项调:
| 模块 | 初级出现频率 | 建议投入 | 必须能答的题 |
|---|---|---|---|
| Java 基础 | 极高 | 30% | == 与 equals、String 三件套、final |
| 集合 | 极高 | 25% | HashMap 原理、ArrayList 对比、线程安全集合 |
| 多线程 | 高 | 20% | 线程状态、线程池参数、sleep 与 wait |
| Spring | 高 | 10% | IOC、AOP、自动配置 |
| MySQL/Redis | 高 | 10% | 索引失效、事务隔离、缓存三问题 |
| JVM/中间件 | 中 | 5% | 内存区域、GC 判断、MQ 定位 |
押题的另一个动作是准备三个“项目钩子”。面试官问完八股一定会转项目,你要提前想好三个能主动抛的点:一个是你用线程池处理过批量任务,一个是你给慢查询加过索引并用 explain 验证,一个是你用 Redis 做过缓存并处理过穿透。每个钩子准备“背景一句、做法两句、结果一句”,被问到时顺着讲,讲完自然把话题带回你熟的领域。这比被动等问强得多。
最后说个血泪经验:我第一次面初级岗时,把 JVM 分代收集背得滚瓜烂熟,结果面试官问“你项目里堆内存设多大、为什么”,我一句答不上来。从那以后我每次准备面试,都把每个原理题强行绑一个项目场景,哪怕场景是模拟项目也要能说清参数怎么来的。原理题答对是及格,原理加场景才是通过。希望帮到你。
本文还有配套的精品资源,点击获取