简介:这份 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,轻量易携带,可打印或导入笔记软件随时复习。目前已有 620 人学习,适合作为初级 Java 面试的清单式复习材料,按模块逐项过题即可快速定位薄弱环节。
1. 刚学完 Java 却不敢去面试:这份 208 道题的清单到底能帮你什么
很多人学完 Java 语法后的第一个困惑不是「怎么写代码」,而是「面试官问我 == 和 equals 的区别,我该怎么答」。课本上讲过的概念,一到面试场景就变成一团浆糊,明明用过 String,却说不清它为什么不可变;明明写过线程,却讲不明白 sleep 和 wait 差在哪。这种「会用但说不清」的状态,几乎是每个零基础转行或刚出校门的人都会经历的阶段。
这份 Java 初级面试题汇总就是冲着这个痛点来的。它把 Java 基础、多线程、反射、对象拷贝、JavaWeb、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/SpringCloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM 十八个模块的常见面试题整理成 208 道带答案的清单,面向的正是刚从学校出来或者刚培训出来、准备第一次 Java 面试的人。它不是让你背题应付考试,而是帮你把「用过」变成「讲得清」,把散落的知识点串成一条能说出口的线。
你不需要先把十八个模块全学完再来看它。入门阶段最有效的用法是:先挑 Java 基础和多线程这两块,把每道题的答案读一遍,遇到看不懂的代码就自己敲一遍跑一遍,让答案里的示例变成你手上的肌肉记忆。下面几章就按这个顺序带你走一遍,从「这到底是什么」到「第一个例子怎么跑通」。
2. 先搞懂这份资源的结构:十八个模块怎么排、先看哪几个
2.1 十八个模块不是平级的,入门先抓三块
拿到一份 208 道题的文档,新手最容易犯的错是从第一题开始按顺序硬啃,啃到反射或者 JVM 就卡住,然后放弃。其实这十八个模块有明确的难度梯度,入门阶段真正需要先吃透的只有三块:Java 基础、多线程、集合相关(散落在 Java 基础模块里)。这三块是后面所有模块的地基,Spring 的 bean 生命周期、MyBatis 的缓存、Redis 的线程模型,追到底都和这三块有关。
Java 基础模块覆盖了 JDK 与 JRE 的区别、== 和 equals、hashCode、final、String 系列、抽象类与接口、IO 流、容器体系这些内容,是面试中出现频率最高、也最容易被追问的部分。多线程模块从并行与并发的区别讲到线程池的七种创建方式、synchronized 锁升级、死锁防止,是初级面试里区分「背过」和「真懂」的分水岭。剩下的反射、对象拷贝、JavaWeb、异常、网络、设计模式属于第二梯队,Spring 全家桶、消息队列、数据库、缓存、JVM 属于第三梯队,等你拿到第一份工作或者准备进阶时再回头补。
入门的话建议先按「Java 基础 → 多线程 → 异常与网络」的顺序走,每看完一个模块,合上文档用自己的话把题目复述一遍,说不清的地方再回去看答案。这个复述动作比反复阅读有用得多,我第一次准备面试时就是靠这个方法发现自己以为懂了其实没懂。
2.2 每道题的答案结构:概念 + 代码 + 结论
这份资源的答案不是干巴巴的一句话定义,而是「先给结论,再给代码示例,最后补一句总结」的结构。以 == 和 equals 那道题为例,答案先说明基本类型比较值、引用类型比较引用,然后给出 String 的三行对比代码,再解释 new String 为什么开辟了新内存,最后落到「equals 默认是引用比较,String 和 Integer 等重写了它变成值比较」。
这种结构对新手特别友好,因为你可以把每道题当成一个小实验来做:把答案里的代码复制到自己的编辑器里,改改变量、换换值,看输出有没有变化。比如把String x = "string"改成String x = new String("string"),再跑一遍x == y,你会亲眼看到结果从 true 变成 false。这种「改一改、跑一跑」的动作,比读十遍文字解释都管用。
提示:读答案时不要跳过代码块。这份资源里很多结论是靠代码示例撑起来的,跳过代码等于只记住了半句话,面试官一追问就露馅。
2.3 怎么判断自己「真的懂了」一道题
一个简单的自测标准:看完一道题的答案后,你能不能不看原文,用三句话讲清楚「它是什么、它和相近概念差在哪、什么场景下会用到」。比如 hashCode 和 equals 那道题,能讲清「hashCode 相同 equals 不一定为 true,因为哈希冲突」「散列表里先比 hashCode 再比 equals」「重写 equals 必须重写 hashCode」这三点,就算过关。
如果讲不出来,说明你只是「看懂了字面」,没有形成自己的理解。这时候别急着看下一题,回到代码示例,把「通话」和「重地」那个 hashCode 相同的例子亲手跑一遍,看看两个不同字符串的哈希值为什么一样。这种具体例子是记忆的锚点,面试时你一紧张,脑子里浮现的往往就是那个跑出 false 的瞬间。
3. 第一个例子怎么跑:从 == 和 equals 开始动手
3.1 准备一个能跑 Java 的环境
动手之前先确认环境。你需要安装 JDK(不是只装 JRE),因为要编译和运行代码。装完后在终端里执行下面两条命令,能看到版本号就说明环境通了:
# 查看 Java 运行时版本 java -version # 查看 Java 编译器版本,能输出版本号说明装的是 JDK 而不是 JRE javac -versionjava -version输出的是运行时环境信息,javac -version输出的是编译器版本。两条都能正常输出,才说明你装的是完整的 JDK。如果第二条报「command not found」,多半是只装了 JRE 或者环境变量没配好,回去补装 JDK 并配置 PATH 即可。这一步看着简单,但它是后面所有例子的前提,环境没通就别往下走。
3.2 跑通第一段对比代码
新建一个文件叫EqualsDemo.java,把下面这段代码敲进去。这段代码来自资源里 == 和 equals 那道题的示例,我加了注释方便你对照:
public class EqualsDemo { public static void main(String[] args) { // 字面量赋值,x 和 y 指向常量池里的同一个对象 String x = "string"; String y = "string"; // new 会在堆内存里新开一块空间,z 指向的是新对象 String z = new String("string"); // 引用相同,结果为 true System.out.println(x == y); // 引用不同,结果为 false System.out.println(x == z); // equals 比较的是值,结果为 true System.out.println(x.equals(y)); // equals 比较的是值,结果为 true System.out.println(x.equals(z)); } }编译并运行:
# 编译源文件,生成 EqualsDemo.class javac EqualsDemo.java # 运行编译后的类 java EqualsDemo预期输出是true、false、true、true四行。如果你看到的结果和这个不一致,先检查是不是把==和equals写混了,或者字符串里的空格导致值不相等。这段代码的关键在于理解x == y为什么是 true:字面量字符串会被放进常量池,x 和 y 拿到的是同一个引用;而new String强制在堆里开辟新空间,所以 z 的引用和 x 不同,==为 false,但equals比较的是字符内容,所以为 true。
3.3 把例子改一改,验证自己的理解
跑通之后别停,做两个小改动验证理解。第一个改动:把String z = new String("string")改成String z = "string",再跑一遍,看看x == z变成什么。第二个改动:自己写一个没有重写 equals 的类,用两个内容相同的对象比较,看看结果是不是 false。
class Cat { private String name; public Cat(String name) { this.name = name; } } public class CatDemo { public static void main(String[] args) { Cat c1 = new Cat("same"); Cat c2 = new Cat("same"); // 没有重写 equals,走的是 Object 的默认实现,比较引用 System.out.println(c1.equals(c2)); } }这段代码输出 false,因为 Cat 没有重写 equals,默认实现就是this == obj。这个实验能让你彻底记住「equals 默认比引用,String 等类重写了才比值」这句话。资源里那道 hashCode 的题也是同样的道理,两个不同字符串的哈希值可能相同,但 equals 为 false,说明哈希相同推不出对象相等。把这两个实验做完,Java 基础模块里最容易混淆的几道题你就真正拿下了。
4. 多线程模块怎么啃:从概念到线程池的入门路径
4.1 先分清并行、并发、进程、线程四个词
多线程模块的第一道坎不是代码,是概念。并行和并发这两个词新手最容易混:资源里的比喻很到位,并发是两个队列共用一台咖啡机,轮流打咖啡;并行是两个队列两台咖啡机,同时打。落到程序里,并发是多个任务在同一个 CPU 核上按时间片交替执行,逻辑上像同时;并行是多核同时处理多个任务,物理上真的同时。
进程和线程的关系则是包含关系:一个程序至少有一个进程,一个进程至少有一个线程,一个进程可以有多个线程来加快执行。守护线程是跑在后台的特殊线程,垃圾回收线程就是典型例子,它不阻止程序退出。把这四个词用自己的话讲清楚,多线程模块后面一半的题就有了落脚点。
4.2 创建线程的三种方式,先跑通最简单的一种
资源里说创建线程有三种方式:继承 Thread 重写 run、实现 Runnable 接口、实现 Callable 接口。入门阶段先把前两种跑通,第三种等你看懂返回值再碰。下面是最基础的 Runnable 写法:
public class RunnableDemo { public static void main(String[] args) { // 实现 Runnable 接口,定义线程要执行的任务 Runnable task = new Runnable() { @Override public void run() { System.out.println("线程运行中:" + Thread.currentThread().getName()); } }; // 把任务交给 Thread 启动 Thread t = new Thread(task); t.start(); } }Runnable只描述「要做什么」,Thread负责「开一个线程去做」。start()才是真正启动线程的方法,它会让 JVM 新开一个执行流去调用run();如果你直接调t.run(),那只是在当前线程里普通地执行了一个方法,根本没有新线程。资源里 run 和 start 那道题考的就是这个区别,run 可以重复调用,start 只能调一次,第二次调会抛异常。
4.3 线程池七种创建方式,先记住最核心的一种
线程池那块资源列了七种创建方式,新手看到newSingleThreadExecutor、newCachedThreadPool、newFixedThreadPool、newScheduledThreadPool、newWorkStealingPool、ThreadPoolExecutor这一串容易发怵。入门阶段你只需要记住一件事:前六种都是对ThreadPoolExecutor的封装,第七种才是最原始、参数最全的创建方式。
import java.util.concurrent.*; public class PoolDemo { public static void main(String[] args) { // 核心线程数 2,最大线程数 4,空闲存活 60 秒,使用有界队列 ThreadPoolExecutor pool = new ThreadPoolExecutor( 2, 4, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10) ); // 提交任务 pool.execute(() -> System.out.println("任务执行:" + Thread.currentThread().getName())); // 用完关闭,否则程序不会退出 pool.shutdown(); } }四个核心参数的含义:核心线程数是常驻的线程数量,最大线程数是任务多时能扩到的上限,空闲存活时间是非核心线程闲多久被回收,工作队列是任务排队的容器。execute只能接 Runnable,submit能接 Runnable 和 Callable 并拿到返回值,这是资源里 submit 和 execute 那道题的答案。跑通这段代码后,再回头看那七种封装方式,你会发现它们只是把这四个参数预设成了不同组合,理解起来就轻松多了。
注意:线程池用完一定要
shutdown(),否则主线程结束后池里的线程还活着,程序不会退出。这是新手最常遇到的「程序卡住不结束」的原因之一。
4.4 锁和死锁:先理解现象再记结论
synchronized 和 Lock 的区别、锁升级、死锁防止这几道题偏理论,入门阶段不用深挖底层,先理解现象。死锁的经典场景是线程 A 拿着锁 a 等锁 b,线程 B 拿着锁 b 等锁 a,两边都不放手。资源里给的防止办法很实用:用带超时的tryLock、优先用并发包里的类、降低锁粒度、缩小同步代码块。
你可以写一个最简单的死锁例子跑一跑,观察程序卡住不动的现象,再用jstack看线程状态,这比背定义直观得多。不过入门阶段跑通一个死锁例子就够了,不用花太多时间在锁升级的细节上,那是你工作一两年后回头看会更有感觉的内容。
5. 新手用这份清单最容易踩的五个坑
5.1 从第一题背到最后一题,背完就忘
现象:按顺序硬啃 208 道题,看到反射和 JVM 就卡住,前面背的也忘得差不多。原因:十八个模块难度差异大,平铺直叙地读没有重点,大脑记不住没有关联的孤立知识点。解决:按第 2 章说的顺序,先吃透 Java 基础和多线程,每道题用自己的话复述一遍,讲不清就回去跑代码,形成「概念—代码—复述」的闭环。
5.2 只看答案不跑代码,面试一追问就露馅
现象:答案读起来都懂,面试官让你手写一个字符串反转或者解释输出结果,就写不出来。原因:阅读是被动输入,写代码和预测输出是主动输出,两者调用的大脑机制不同。解决:每道带代码的题都亲手敲一遍、跑一遍,再改几个参数看输出变化。资源里 String 反转、Iterator 遍历、线程池创建这些题都有现成代码,照着跑是最快的上手方式。
5.3 把 equals 和 hashCode 的结论记反
现象:面试时答「hashCode 相同 equals 一定为 true」,被面试官当场纠正。原因:这两个方法的契约关系容易记混,只记结论不理解原理就会记反。解决:回到「通话」和「重地」那个例子,亲手跑一遍,看到两个不同字符串哈希值相同但 equals 为 false,这个反例比任何口诀都记得牢。再补一句「重写 equals 必须重写 hashCode」,这道题就完整了。
5.4 线程池用完不关闭,程序卡住不退出
现象:跑完线程池的示例代码,控制台不再输出,但程序就是不结束,得手动强制停止。原因:线程池里的线程默认是非守护线程,主线程结束后它们还活着,JVM 不会退出。解决:在示例末尾加pool.shutdown(),它会等已提交的任务执行完再关闭;如果希望立即中断,用shutdownNow()。这个坑几乎每个新手都踩过,记住「线程池用完要关」就行。
5.5 把这份清单当成唯一的学习材料
现象:只背这 208 道题,面试时遇到稍微变形的追问就答不上来。原因:面试题是知识点的切片,不是知识体系本身,只背切片无法应对组合提问。解决:把这份清单当索引,每道题背后对应一个知识点,答不上来时回到教材或官方文档把那个知识点补完整。清单帮你定位薄弱环节,补课还得靠系统学习。
6. 下一步学什么:从背题到能讲清的三步走
入门之后最容易迷失的地方,是不知道 208 道题背完之后该往哪走。我的建议是把学习拆成三步,每一步都有明确的验收标准,避免陷入「一直在看、一直没底」的状态。
第一步,用两周时间把 Java 基础和多线程两个模块的题全部过一遍,每道题做到「不看答案能讲三句话」。验收方式是找身边的人或者对着录音讲一遍,卡壳的地方标记出来重跑代码。这一步的目标不是记住所有答案,而是建立「概念—代码—现象」的联想,让你在面试现场能顺着一个例子把结论推出来。
第二步,用一周时间补异常、网络、集合底层这三块。异常那块重点搞清楚受检异常和运行时异常的区别、try-catch-finally 的执行顺序;网络那块把 TCP 三次握手、HTTP 常见状态码过一遍;集合底层把 HashMap 的 put 流程、ArrayList 扩容机制弄明白。这三块是初级面试的高频追问区,资源里对应的题目都有,配合代码跑一遍即可。
第三步,等你拿到面试机会或者入职之后,再回头补 Spring、MySQL、Redis、JVM 这几个模块。这些内容需要一定的项目经验做支撑,零基础阶段硬啃容易挫败。下面这张表可以帮你判断每个模块该在什么阶段投入精力:
| 模块 | 建议阶段 | 投入时间 | 验收标准 |
|---|---|---|---|
| Java 基础 | 第一周 | 5 天 | 能讲清 == 与 equals、String 系列、容器区别 |
| 多线程 | 第二周 | 5 天 | 能跑通线程创建和线程池示例,讲清 sleep 与 wait |
| 异常与网络 | 第三周 | 3 天 | 能说清异常分类和常见状态码 |
| Spring 全家桶 | 入职前后 | 按需 | 能说清 bean 生命周期和依赖注入 |
| MySQL 与 Redis | 入职前后 | 按需 | 能说清索引原理和缓存穿透 |
从那以后我每次准备面试,都会强制自己走一遍「跑代码—复述—找反例」的流程,不再单纯地读答案。这个习惯让我在几次面试里被追问时都能顺着例子讲下去,而不是背完就忘。希望这份清单也能帮你把第一次 Java 面试的门槛降下来,从跑通第一个 == 和 equals 的例子开始,一步一步走进去。
本文还有配套的精品资源,点击获取