简介:这份 Java 初级面试题汇总文档面向刚从学校毕业或培训结业的求职者,帮助其在面试前系统梳理高频考点、建立完整的知识框架。内容按十八个模块组织,涵盖 Java 基础、多线程、反射、对象拷贝、JavaWeb、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/SpringCloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis 与 JVM,共收录 208 道题目,并配有答案与代码示例,如 JDK 与 JRE 的区别、== 与 equals 的比较规则、hashCode 与 equals 的关系等均有源码级解读。压缩包内为 1 个 docx 文件,大小约 155KB,轻量便携,便于打印或离线查阅。目前已有 623 人学习,适合作为初级 Java 面试的随身清单,按模块逐项自测、查漏补缺。
1. 初级 Java 面试到底考什么:208 道题里藏着三条得分主线
很多人背了一堆“Java 初级面试题”,进考场还是被问懵,原因不在题背得少,而在没看清这场面试的评分逻辑。初级岗的面试官通常不指望你讲清 JVM 调优的全部细节,他要确认三件事:基础概念有没有硬伤、常用 API 能不能说清行为差异、遇到场景题会不会把知识点串起来。这份 208 道、分十八个模块的清单,恰好把这三条主线铺开了——Java 基础、集合、多线程是主战场,Spring/MyBatis/MySQL/Redis 是加分项,JVM、消息队列、Zookeeper 属于“问到能答、答得不离谱”的防守区。
拿分的关键不是逐题死背,而是先分清哪些题必须张口就来(如==与equals、ArrayList与LinkedList、sleep与wait),哪些题只要给出结论加一句解释(如Math.round(-1.5)等于 -1),哪些题要能落到代码或场景(如线程池创建方式、synchronized锁升级)。下面按考点模块拆开讲,每道高频题都给答题思路,你照着练,比通读十遍文档管用。
2. Java 基础与集合:八道必背题和它们的答法
2.1 概念辨析题:先给结论,再补一句原理
初级面试最爱考“A 和 B 有什么区别”,这类题翻车的典型是答成两段百科。面试官想听的是:一句话结论 + 一个能验证结论的细节。以==和equals为例,标准答法是先说“==对基本类型比值、对引用类型比地址;equals默认也是比地址,但 String、Integer 等重写后变成比值”,然后主动补一个例子:new String("i")和字面量"i"用==是 false,用equals是 true。这个补充能证明你不是背的。
同类题还有 JDK 与 JRE(JDK 含 JRE 和 javac 等工具)、String、StringBuffer、StringBuilder(可变性、线程安全、性能三层递进)、接口与抽象类(实现方式、构造方法、多实现与单继承、访问修饰符)。答这类题时,把“区别”拆成两到三个维度说,每个维度一句话,比堆砌长句更稳。
2.2 行为判断题:答案反直觉的题最容易被追问
有些题的正确答案和直觉相反,面试官专门拿来测你是不是真理解。比如“两个对象hashCode()相同,equals()一定为 true 吗”,答案是不一定。答题思路是先否定,再解释哈希冲突:哈希值相同只说明落在同一个桶,桶里可能挂多个元素,是否相等还要靠equals判断。能举出“通话”和“重地”哈希值相同但equals为 false 的例子,基本就满分了。
再如Math.round(-1.5)等于 -1,不是 -2。答的时候说清规则:四舍五入在数轴上向正方向取整,正 0.5 进位,负 0.5 直接舍去。还有“抽象类必须有抽象方法吗”,答案是不需要,抽象类可以一个抽象方法都没有,只是不能被实例化。这类题答错不是知识漏洞,是没记住边界,建议单独列一张“反直觉题”清单反复过。
2.3 集合对比题:用表格思维答题,别背整段
集合模块是初级面试的密集区,ArrayList与LinkedList、HashMap与Hashtable、ArrayList与Vector、Array与ArrayList、List/Set/Map的区别,几乎每场必问。答题时在脑子里摆一张表:数据结构、线程安全、是否允许 null、扩容方式、随机访问效率。比如ArrayList与LinkedList,前者动态数组、随机访问快、中间增删要移动元素;后者双向链表、增删快、随机访问要遍历指针。最后补一句使用建议:“频繁读用 ArrayList,频繁插删用 LinkedList”,面试官会觉得你有选型意识。
HashMap的实现原理是这一块的分水岭题。答题顺序建议:底层是数组加链表加红黑树;put时用 key 的hashCode算桶位置;哈希冲突少时用链表,冲突多(链表长度到阈值)转红黑树;扩容时重新分配。不用背源码行号,把“数组—链表—红黑树—扩容”这条链说顺就够初级岗了。HashSet基于HashMap实现、ConcurrentHashMap替代Hashtable做线程安全场景,这两句要能脱口而出。
2.4 真题演练:从“怎么用”到“为什么”
看一道典型问法:“如何实现数组和 List 之间的转换?”答题不能只说方法名,要带出坑。数组转 List 用Arrays.asList(array),但返回的是固定长度视图,往里add会抛UnsupportedOperationException;List 转数组用toArray(),推荐传入目标类型数组避免类型转换问题。
// 数组转 List:注意返回的是固定长度视图,不能 add/remove String[] array = new String[]{"a", "b"}; List<String> fixed = Arrays.asList(array); // 需要可变 List 时,包一层新的 ArrayList List<String> mutable = new ArrayList<>(Arrays.asList(array)); mutable.add("c"); // 正常执行 // List 转数组:传入类型化数组,避免返回 Object[] String[] back = mutable.toArray(new String[0]);这段代码的讲解点在于:Arrays.asList的返回类型是java.util.Arrays$ArrayList,不是java.util.ArrayList,两者名字像但行为不同,这是初级面试的高频陷阱。参数上,toArray(new String[0])里的空数组只是告诉 JVM 返回类型,长度由 List 决定,不必预先算大小。能把这个区别讲出来,比背十个方法名更有说服力。
3. 多线程高频考点:线程池、锁和那些必须说清的差异
3.1 线程基础:状态、创建方式与两组必考对比
多线程是初级面试里最容易拉开差距的模块,因为概念多、易混点多。先守住基础盘:创建线程三种方式(继承Thread、实现Runnable、实现Callable),线程六种状态(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED),这两组要能按顺序说全。Runnable与Callable的区别落在“有没有返回值、能不能抛受检异常”上,一句话说清即可。
真正的高频对比是sleep()与wait():前者来自Thread、不释放锁、时间到自动恢复;后者来自Object、释放锁、需要notify/notifyAll唤醒。答题时按“所属类、是否释放锁、唤醒方式”三个维度说,条理立刻出来。notify与notifyAll的区别则要补一句:notifyAll把等待池里所有线程移到锁池参与竞争,notify只唤醒一个且由虚拟机决定,所以实际开发更推荐notifyAll,避免信号丢失。run()与start()的区别也别漏:start才真正启动新线程,run只是普通方法调用,可以重复调,start只能调一次。
3.2 线程池:七种创建方式和五个状态
线程池是初级岗的高频压轴题。创建方式要能说出七种:newSingleThreadExecutor、newCachedThreadPool、newFixedThreadPool、newSingleThreadScheduledExecutor、newScheduledThreadPool、newWorkStealingPool,以及最核心的ThreadPoolExecutor。答题重点不是报菜名,而是点明“前几种都是对ThreadPoolExecutor的封装”,并各用一句话说特点:单线程池保证顺序执行;缓存线程池复用空闲线程、闲置 60 秒回收;固定线程池控制并发数、任务超出后排队。
线程池五个状态(RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED)属于“问到要能答”的题,记关键词即可:SHUTDOWN 不收新任务但处理队列,STOP 连队列也不处理并中断线程。submit()与execute()的区别要答出“submit 能接 Callable 并返回 Future,execute 只接 Runnable 无返回值”。如果面试官追问参数含义,把核心线程数、最大线程数、空闲存活时间、工作队列、拒绝策略这五个说清,初级岗就稳了。
3.3 锁与并发安全:synchronized、volatile、Lock 三角关系
锁这块的题有个特点:单看每道都不难,连起来问就容易乱。建议按“是什么—怎么用—和谁比”组织答案。synchronized底层靠monitorenter/monitorexit指令实现,Java 6 之后有偏向锁、轻量级锁、重量级锁的升级过程,目的是降低锁开销。锁升级的原理可以这样讲:第一次访问时对象头记录线程 id 进入偏向锁;别的线程来竞争就升级为轻量级锁,靠自旋尝试;自旋多次拿不到再升级为重量级锁。
synchronized与volatile的区别要落在“volatile 只保证可见性、不保证原子性、不阻塞线程”,synchronized三者都能保证。synchronized与Lock的区别则是“自动 vs 手动、能否知道获取锁成功、锁的范围”。ReentrantLock必须手动unlock,所以标准写法是lock()后紧跟try/finally:
Lock lock = new ReentrantLock(); lock.lock(); try { // 临界区:这里放需要互斥执行的逻辑 System.out.println("获得锁"); } finally { // 必须放在 finally,异常时也能释放,避免死锁 lock.unlock(); }讲解点在于finally不是可选项:如果临界区抛异常而没释放锁,其他线程会永久阻塞,这就是“手动锁用不好会死锁”的真实含义。参数上,ReentrantLock还支持公平锁构造参数和tryLock(timeout)超时获取,后者正是防止死锁的常用手段。死锁的四个必要条件(互斥、持有并等待、不可剥夺、循环等待)和预防手段(降低锁粒度、减少同步块、用并发类替代手写锁)也要能说,面试官常顺着死锁追问“你怎么避免”。
3.4 真题演练:并发安全怎么答才不空
“在 Java 程序中怎么保证多线程的运行安全?”这题很多人答成“加锁”两个字,太薄。完整思路分三层:第一层用现成的线程安全类,如java.util.concurrent下的ConcurrentHashMap、AtomicInteger;第二层用synchronized自动锁;第三层用Lock手动锁并配合try/finally。再补一句ThreadLocal的思路——给每个线程独立副本,避免共享,经典场景是数据库连接和 session 管理。
atomic的原理也常被追问:靠 CAS(比较并交换)加volatile加 native 方法保证原子操作,避免synchronized的高开销。答题时点出 CAS 的“比较—交换”语义即可,不必展开 ABA 问题,除非面试官主动问。这一模块的复习方法建议是:把“区别类”题目两两成对列出来,每对写三行答案,考前只看这张对照表。
4. 框架与中间件:Spring、MyBatis、MySQL、Redis 的常考面
4.1 Spring 与 Spring Boot:从 IOC、AOP 说到自动配置
框架部分初级岗问得不深,但几个核心概念必须张口就来。Spring 的两大基石是 IOC(控制反转,对象创建和依赖交给容器)和 AOP(面向切面,把日志、事务等横切逻辑抽出来)。答题时别只背名词,补一句“IOC 的好处是解耦、便于测试”,AOP 补“底层常用动态代理实现”。Spring MVC 的请求流程可以按“前端控制器—处理器映射—处理器适配—视图解析”这条线说,初级岗说清主干即可。
Spring Boot 的高频点是“约定优于配置”和自动配置:起步依赖简化依赖管理,自动配置根据类路径上的 jar 推断该装配什么,内嵌容器让应用可直接运行。Spring Cloud 在初级面试里通常只问“解决什么问题”——服务注册发现、配置中心、负载均衡、熔断这些方向,能说出两三个组件的作用就够,不必深入源码。
4.2 MyBatis 与 Hibernate:两个 ORM 的取舍题
“MyBatis 和 Hibernate 有什么区别”是经典对比题。答法:Hibernate 是全自动 ORM,表与对象映射由框架管理,开发快但 SQL 不够可控;MyBatis 是半自动,SQL 写在映射文件里,灵活、易优化,适合复杂查询。再补一句“互联网项目多用 MyBatis,因为 SQL 可调优”,这是面试官爱听的实践判断。MyBatis 的#{}与${}区别也要会:前者预编译占位、防注入;后者字符串拼接、有注入风险,除非动态表名等特殊场景否则不用。
4.3 MySQL 与 Redis:索引、事务、缓存三件套
MySQL 在初级面试里集中在三块:索引(B+ 树结构、最左前缀原则、索引失效场景)、事务(ACID、四种隔离级别、脏读/不可重复读/幻读)、SQL 优化(避免select *、看执行计划、少用函数包裹索引列)。答题时把“索引为什么用 B+ 树”说成“矮胖、磁盘 IO 少、叶子节点有序便于范围查询”,比背定义有效。
Redis 的高频点是数据类型(String、Hash、List、Set、ZSet)及场景、缓存穿透/击穿/雪崩的区别与应对、持久化(RDB 快照与 AOF 日志)。这三类缓存问题建议按“是什么—什么后果—怎么防”三段答:穿透是查不存在的数据,用布隆过滤器或空值缓存;击穿是热点 key 失效,用互斥锁或逻辑过期;雪崩是大量 key 同时失效,给过期时间加随机值。能这样分层,说明你不是只背了名词。
4.4 消息队列与 JVM:防守区的答题底线
RabbitMQ、Kafka、Zookeeper 和 JVM 在初级岗属于“问到不能哑”的区域。RabbitMQ 记交换机类型和“生产—交换机—队列—消费”模型;Kafka 记高吞吐、分区、副本、消费组这几个关键词;Zookeeper 记“分布式协调、选主、配置管理”的定位。JVM 则守住内存区域划分(堆、栈、方法区、程序计数器、本地方法栈)、对象创建与回收的基本流程、常见垃圾回收算法(标记清除、复制、标记整理)和分代思想。初级岗不要求你调参,但“堆和栈分别放什么”“什么对象会被回收”这类问题要答得干脆。
5. 易错点:五类最容易丢分的题,错在哪、怎么改
5.1 把“不一定”答成“一定”
最典型的失分是 hashCode 与 equals 的关系题。错在把“equals 相等则 hashCode 一定相等”反推成“hashCode 相等则 equals 一定相等”。为什么错:哈希冲突是散列表的常态,相同哈希值只是落在同一桶。怎么答对:先明确否定,再解释冲突,最后补一句“反过来 equals 相等则 hashCode 必须相等,所以重写 equals 必须重写 hashCode”。这个反向补充是加分项。
5.2 混淆“视图”和“新集合”
Arrays.asList返回固定长度视图、Collections.unmodifiableCollection返回只读视图,很多人答成“转成了 ArrayList”。错在没区分包装与拷贝。怎么答对:说清“视图共享底层数据、结构不可改”,需要可变就new ArrayList<>(...)。同理,List.of这类不可变集合也不能add,答题时点明“不可变”三个字。
5.3 线程池题只报名字不说封装关系
问“创建线程池有哪几种方式”,只背七个方法名而不说“前六种都是ThreadPoolExecutor的封装”,会被认为理解停在表面。怎么答对:先给七种,再点明核心是ThreadPoolExecutor,最后补一句“实际项目建议手动创建并明确参数,避免无界队列导致内存问题”。这一句能把答案从“背过”拉到“用过”。
5.4 锁的对比答成单方面罗列
synchronized与Lock、volatile与synchronized的题,常见错误是把一方优点说一堆、另一方不提。怎么答对:固定用“维度对照法”——自动/手动、是否释放锁、能否中断、能否知道获取成功、适用场景,每个维度两边各一句。这样即使某条记不全,结构也在,面试官能看出你的思维框架。
5.5 场景题只给结论不给取舍
“如何决定用 HashMap 还是 TreeMap”“ArrayList 还是 LinkedList”,只答“看情况”等于没答。怎么答对:给出判断依据——需要按 key 有序遍历选 TreeMap,纯增删查选 HashMap;读多用 ArrayList,插删多用 LinkedList。再补一句“数据量和操作比例决定选型”,把结论落到场景上。
6. 考前怎么用这份清单:三轮过题法和一个答题习惯
这份 208 题的清单,正确的用法不是从第一题背到最后一题,而是分三轮。第一轮按模块扫一遍,只做一件事:给每道题标一个等级——A 是必须张口就来的(==与equals、集合对比、sleep与wait、线程池创建、Spring IOC/AOP、MySQL 索引、Redis 缓存三问题),B 是能说结论加一句解释的(Math.round、抽象类能否无抽象方法、notify与notifyAll),C 是问到能答不冷场的(JVM 细节、Kafka 副本、Zookeeper 选主)。标完你会发现 A 类其实不到一半,先把这一半练到条件反射。
第二轮只练 A 类,方法是“合上答案自己讲一遍,讲不顺的做记号”。讲的标准是:结论在前、原理在后、例子收尾。比如讲HashMap原理,先说“数组加链表加红黑树”,再说 put 的流程,最后补扩容。讲不出来的题不要反复读,直接回到原文找那句关键结论,用自己的话重写一遍,写下来的版本才是你能说出口的版本。
第三轮做交叉串联,把容易一起问的题编成组练:==/equals/hashCode一组,ArrayList/LinkedList/Vector一组,sleep/wait/notify一组,synchronized/volatile/Lock一组,MySQL 索引/事务/优化一组。每组准备一个“如果面试官继续追问”的备用答案,比如集合组备“扩容机制”,锁组备“死锁预防”。这一轮的目的是让知识点从孤岛变成网,被追问时不慌。
最后说一个我自己踩过坑才养成的习惯:每道题答完,强制补一句“在实际项目里这意味着什么”。讲Arrays.asList就补“所以需要可变集合时要包一层”,讲线程池就补“所以生产环境建议手动指定队列容量”。初级面试官判断你是不是“只会背”,往往就看这一句。从那以后我每次准备这类清单,都会给 A 类题逐条写一句场景补充,答起来明显更稳。希望帮到你。
本文还有配套的精品资源,点击获取