简介面向Java初学者与求职者的一份面试题合集聚焦基础与代码实战两大板块。资源整理面向对象特征、String与StringBuffer、int与Integer、异常机制、Servlet生命周期、ArrayList/Vector/LinkedList对比等高频考点适合系统刷题、查漏补缺与面试前冲刺。压缩包为PDF格式共1个文件大小约267KB便于直接阅读、打印或导入笔记软件。该资源已有1549人学习属于轻量但覆盖较全的基础题集。内容预览显示除概念解析外还包含19道代码题可帮助读者从原理理解过渡到动手实现122道基础题则按知识点分类答案紧贴考点展开适合作为日常复习提纲或面试速查手册。1. 122道基础题加19道代码题这份题集到底该怎么用把一份“Java面试题及答案集锦”从头到尾背三遍再去面试照样可能挂——这是我见过最多的刷题翻车现场。122道基础题覆盖语法、集合、并发、JVM和IO19道代码题基本就是手写环节的常客这套结构本身没问题问题出在把它当“百科”而不是当“考纲”。适合校招实习、社招跳槽前做系统自测的人方法是倒过来用拿它做模拟面试、错题定位和追问预判。在背答案之前先搞清楚这141道题里哪些是开场必答、哪些是追问深挖、哪些是冷门加分项后面的复习才不会走弯路。2. 拆解基础题122道先分层再复习把背答案变成讲答案2.1 先给122道基础题分个层核心必答、高频追问、冷门边界拿到题集第一件要做的事不是翻开第一题开始背而是先把122道题按面试权重分成三层。常见做法是按“开场题、追问题、拔高题”分我用的是A、B、C三层。A层是开场必答大约占四成。面向对象三大特性、和equals的区别、String为什么不可变、ArrayList和LinkedList怎么选、HashMap的put流程、异常的分类、线程的几种状态、volatile和synchronized的区别、JVM内存区域、类加载的双亲委派机制。这类题答不好后面的面试氛围会很僵几乎是从头到尾都要用的地基。B层是高频追问大约占三成半。ConcurrentHashMap的实现、线程池的核心参数和拒绝策略、CAS和AQS、垃圾回收算法、强软弱虚引用、泛型擦除、反射的底层、序列化、NIO和传统IO的差别。面试官常在A层题目答案里顺手挑一个点往深问这些就是被追问的目标。C层是冷门边界大约占两成半。位移运算、位运算技巧、阻塞队列的实现细节、零拷贝、JIT编译、逃逸分析、类加载的触发条件。这些题不是人人都会问但问出来通常是为了区分同一水平段的候选人。分层理由很实际复习时间有限先把A层练到不看答案也能流利讲再把B层补上C层按岗位要求取舍。如果离面试只有两周C层可以直接降级为“看一遍、混个眼熟”别让冷门题吃掉核心题的复习时间。提示如果目标岗位明确不涉及中间件调优或底层开发C层的内容可以只看标题和一句话结论不值得为它牺牲A层的熟练度。2.2 三遍复习法先读答案再闭卷复述最后写一页纸分层之后进入执行。我一般会把每一道题的复习拆成三遍而不是“记一遍、背一遍、再背一遍”。第一遍只读答案目标不是记住而是把答案里出现的不认识术语全标出来。比如答案写“HashMap在JDK 1.8之后用数组加链表加红黑树”那“红黑树”“树化阈值”“扰动函数”这些词都要单独查一次。这一遍解决的问题是“答案每个字都认识但连起来看不懂”。第二遍合上答案把题目当面试题自己出声讲一遍。讲不顺的地方就是真正薄弱的地方“大概就是这个意思”这种话落到录音里你自己都能听出来。这一遍要对着录音讲不能只在脑子里过因为大脑会自动补全你没讲出口的内容。第三遍是写一页纸。拿一张A4纸把题目的关键词、核心结论、一个例子、一个坑点写在四行以内。比如“HashMap put流程hash扰动→定位→冲突→链表/树→扩容”再加一句“链表超8且数组超64才树化”。这一页纸的价值是考前半小时能快速过完一整轮A层。2.3 用一张自测表管理进度避免复习一个月还在前50题分好层、定好三遍法之后进度管理就是另一道坎。我的习惯是做一张自测表每天只推进10道题但每道题留三个记录字段自评分、卡壳点、追问点。题目编号分层自评分1-5卡壳点追问点A-07 HashMap put流程A3扩容时机说反了树化阈值8和64的关系A-12 线程状态转换A4wait和sleep分不清谁持有锁谁释放锁B-03 CAS原理B2没讲ABA问题版本号怎么用这张表有两个作用。一是防“沉没成本式刷题”——如果你连续一周都在前面的题上打转表上的分层标记直接告诉你A层还剩多少没碰。二是面试回来以后可以对着表反查被问倒的题是不是B层漏掉了被追问卡住的点是不是自评里已经标红过很多人的问题是复习了两个月还在刷前50题后面将近六成的内容完全没看这类人往往就是没做分层和进度管理。自测表不需要花哨电子表格或者纸质表格都可以但每天必须更新。复习到后期这张表就是你的错题本起点后面第6章会讲怎么把它升级成面试复盘系统。3. 代码题19道的手写训练单例、排序与并发题的三种练法3.1 代码题19道的常见分类哪些题几乎必考代码题和基础题完全不是一回事。基础题考察“知不知道”代码题考察“在限定时间内能不能写对”还要能讲清楚“为什么这么写”。从这份题集的常见结构看19道题大致落在五个方向。数据结构类链表反转、二叉树层序遍历、括号匹配、数组去重、TopK问题。这类题不依赖竞赛级算法15分钟内能写完最容易考。算法基础类快排、二分查找、字符串翻转、最长公共前缀。并发类两个线程交替打印、生产者消费者模型、线程池的简化实现。设计模式类单例模式是绝对高频工厂模式偶尔出现。应用类手写LRU缓存、手写一个简化版HashMap。这个分类的价值在于训练方式可以复用。数据结构类和算法基础类拼的是基础功并发类和设计模式类拼的是对Java线程模型和语言机制的理解应用类拼的是工程习惯比如边界处理和复杂度分析。拿到19道题以后先按这五类归位再决定练习顺序我一般建议先练单例、链表反转、交替打印、LRU这四个因为它们每道都能引申出三四个追问性价比最高。3.2 手写单例模式五种写法与面试官追问点单例几乎是代码题的默认第一题不是因为难是因为它能一次性考察线程安全、锁、类加载时机、序列化风险四个点。19道题里如果只准备一道通常就是这道。常见做法是准备五种写法饿汉式、懒汉式、双检锁、静态内部类、枚举。饿汉式最简单但容易被认为“提前实例化浪费资源”懒汉式加了锁但性能差双检锁是高频答案静态内部类利用类加载机制实现懒加载枚举是很多面试资料里推荐的写法还能防序列化破坏单例。public class Singleton { // volatile 防止指令重排保证多线程下拿到完整初始化的对象 private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance null) { // 第一重检查避免已初始化后仍进同步块 synchronized (Singleton.class) { // 锁粒度只锁初始化过程 if (instance null) { // 第二重检查防止两个线程同时通过第一重检查 instance new Singleton(); } } } return instance; } }代码里三个点要能讲清楚volatile为什么必须加是因为new对象在指令层面是分配内存、初始化、赋值三步不加volatile可能让另一个线程拿到未初始化完成的引用第一重检查提升性能避免每次getInstance都抢锁第二重检查保证只有一个实例。面试官最常见的追问是“能不用锁吗”这时候静态内部类就是答案。public class SingletonHolder { private SingletonHolder() {} private static class Holder { private static final SingletonHolder INSTANCE new SingletonHolder(); } public static SingletonHolder getInstance() { return Holder.INSTANCE; } }静态内部类的关键点是Holder不会被主动加载只有getInstance被调用时才会触发类初始化由JVM的类加载机制保证线程安全。练这道题时不要只背代码要把每个关键词背后的为什么都过一遍。面试时一旦被问“你这个锁会不会成为性能瓶颈”能不能接上静态内部类方案就是这道题拿高分和拿及格分的分界线。3.3 手写一个简单的LRU缓存结构设计与边界测试LRU是应用类代码题里出现频率很高的那道它考察两个能力知不知道哈希表加双向链表这个经典结构能不能把访问顺序维护写对。import java.util.HashMap; import java.util.Map; public class LRUCache { static class Node { int key, value; Node prev, next; Node(int key, int value) { this.key key; this.value value; } } private final int capacity; private final MapInteger, Node map new HashMap(); private final Node head new Node(-1, -1); // 哨兵节点简化边界判断 private final Node tail new Node(-1, -1); public LRUCache(int capacity) { this.capacity capacity; head.next tail; tail.prev head; } public int get(int key) { Node node map.get(key); if (node null) return -1; moveToHead(node); // 每次访问都提到头部表示最近使用 return node.value; } public void put(int key, int value) { Node node map.get(key); if (node ! null) { node.value value; moveToHead(node); return; } node new Node(key, value); map.put(key, node); addToHead(node); if (map.size() capacity) { Node last removeTail(); // 超出容量时淘汰最久未使用的尾部节点 map.remove(last.key); } } private void moveToHead(Node node) { removeNode(node); addToHead(node); } private void removeNode(Node node) { node.prev.next node.next; node.next.prev node.prev; } private void addToHead(Node node) { node.next head.next; node.prev head; head.next.prev node; head.next node; } private Node removeTail() { Node last tail.prev; removeNode(last); return last; } }这段代码要重点讲三个设计决定一是用哨兵节点head和tail避免增删时判断prev或next是否为null这是链表题的通用简化手段二是get的时候也要执行moveToHead面试时经常有人把“读不算访问”搞错导致淘汰策略不对三是map只存key到节点的引用节点自带前后指针这样get和put都是O(1)。写完以后一定要跑边界capacity为1时的覆盖、重复key的更新、get一个不存在的key。很多人代码写完没跑边界就交给面试官结果被一个“capacity1”的用例打回。实战里这一条能刷掉相当一批候选人。3.4 代码题的训练节奏先默写、再变形、最后限时19道代码题的训练节奏和三遍法类似但更强调“手不能生”。第一轮默写拿到题先盖住答案自己写写不出来就抄一遍第二天再默一次。默写不是培养记忆力而是让你尽早暴露“以为自己会写、真写就断片”的问题。第二轮变形在原始题上改条件比如单例改成“支持懒加载且参数可配置”LRU改成“要求线程安全”链表反转改成“反转从m到n的区间”。变形是练习理解边界最有效的方式因为原题答案只覆盖单一场景而面试官特别喜欢在代码题上做小改动。第三轮限时每道题控制在10到15分钟在手写板上写或者纸上写不能用IDE自动补全。写完以后用嘴给自己讲一遍代码用了什么数据结构、为什么选它、时间复杂度多少、边界怎么处理。面试官通常会在你写完代码后说“讲讲你的思路”这一关过不了代码写对了也拿不到满分。4. 答案集锦的实战用法答题框架、追问预判与模拟面试4.1 答案集锦的正确打开方式从“背会”到“讲会”题集里的答案是文字面试需要的是声音。这两者之间的差距是很多人刷完题集依然面试失利的主要原因。文字答案可以反复读、不断句口语回答不行。所以我们得做一次转换把每道题的答案拆成“一句话结论”加“三个关键词”加“一个举例”。先说一句话结论。比如“CopyOnWriteArrayList是读写分离的线程安全List”。这句话是回答的主干后面展开都围绕它。再说三个关键词比如“写时复制、快照遍历、弱一致性”。最后补一个举例比如“读多写少的配置场景”。面试时先说不超过20个字的一句话结论再逐层展开关键词比对着题集答案从头念一遍要清晰得多。很多人背题集最大的问题就在这答案背得很完整但面试官听完第一句就能感觉到是在背稿子。把答案重新组织成“结论先行”的结构听起来就像自己的思考过程而不是背稿这一点比多背十道题更有用。4.2 答题框架是什么、为什么、怎么用、坑在哪遇到没准备过的新题时一套固定的答题框架能防止当场懵住。常见做法是用“是什么→为什么→怎么用→坑在哪”四步展开这个框架和题集里的答案结构高度兼容。步骤要回答的内容以“volatile可见性”为例是什么一句话给概念下定义volatile是轻量级的同步机制保证可见性与有序性为什么说底层原理或设计动机写volatile变量会插入内存屏障强制把工作内存的修改刷回主内存怎么用给一个明确的应用场景单例双检锁里的标志位、多线程下的状态开关坑在哪说边界和注意事项不保证原子性count这种复合操作不能靠它保证线程安全用这个框架去套题集的每一道A层题会发现绝大多数答案本身就能按这四步切分。平时复习时有意做一次“四步切分”真到了面试现场即使遇到陌生的衍生题也能按这套结构讲出东西而不是挤牙膏。4.3 用题集预判追问每个答案背后都藏着三连问题集的答案通常只写到“让多数面试官满意的深度”但面试官一定会在答案里挑一个点继续挖。预判追问是最值得投入的复习动作。方法很简单把答案里的数字、限制性词汇、对比性词汇全部圈出来每个圈出来的词都可能是追问点。举个例子答案写“JDK 1.8的HashMap在链表长度超过8且数组长度超过64时转红黑树”。圈出来的就是“8”“64”“1.8”“红黑树”。对应追问就是为什么是8不是9为什么需要数组长度到64才树化JDK 1.7和1.8的HashMap有什么不同红黑树和链表的复杂度差多少预判追问的正确姿势是在自测表的“追问点”一栏里每道题给自己出两个问题然后尝试当场回答。这个过程比多背二十道题更有效。面试官的大部分问题本质上就是“把你刚说的话往深推一层”题集的价值在这里体现得最明显——它给出的答案密度足够高你能从里面挖出的追问点就越多。4.4 模拟面试的实操步骤录音、回放、对照答案最后一步是把题集当模拟试卷用。常见做法是每周安排一到两次模拟面试每次25到30分钟流程固定为三块A层随机抽10题口答、B层抽2题深挖、现场抽1道代码题手写。模拟面试最好找一个人帮忙提问并追问找不到就用录音。提问的人不需要懂Java他只需要照着题集问题清单问然后在你回答完之后追加一句“为什么”或“举个例子”。回放录音时对照答案重点听三处有没有用“嗯”“那个”这类填充词每一句话是不是完整的“主语加谓语”追问问倒的那道题原因到底是没听懂问题还是没掌握知识点。我见过不少候选人模拟面试时答得挺流畅一录回放就发现全是半句话。这是致命的因为面试官每天听十几个人答题对“半句话”的容忍度很低。模拟面试不是为了押题是为了提前暴露表达问题这套流程每练一次都能从录音里挑出两个以上的表达毛病。5. 避坑记录刷题集常见的4个翻车现场与补救方法5.1 现象答案背得滚瓜烂熟一追问就卡壳这是刷题集最常见的翻车。候选人能把HashMap的put流程一字不差背下来面试官追问一句“为什么链表不一直用下去非要转红黑树”当场僵住。前面几道题答得多顺利这一瞬间造成的反差就有多刺眼面试氛围会明显变冷。原因在于把记忆单元当成了“整段答案”而不是“答案里的知识点链路”。背下来的是整段话一旦被打断或者被绕到分支问题就不知道接着讲哪一句甚至会把还没讲完的下一句也忘掉。这就像唱歌只记住了伴奏带伴奏带一停全盘卡壳。解决方法是把每道题的答案改成“结论原因数字”三段拆开记。结论一句话原因一到两句数字单独记牢。追问通常都是针对数字去的数字背后的因果链想明白了再怎么追问都接得上。复习时每道题都问自己一遍“这个数字为什么是它”比多背十遍整段答案都管用。5.2 现象代码题在纸上能写一问运行结果就出错另一种常见翻车是代码题写出来了面试官让在脑子里跑一遍说出某个输入下每步的输出结果结果说错。比如手写LRU写完没测容量为1的情况被问“容量1先put(1,1)再put(2,2)get(1)返回什么”答错成返回1实际应该返回-1。原因很清楚练习时过度依赖IDE写完直接点运行没有养成“人肉执行”的习惯。面试现场没有IDE连编译报错都看不到代码必须能在脑子里跑起来。很多人在白板上写代码写得飞快但一让人肉执行就露怯因为从来没练过这一步。解决方法是练习时坚持“写完后人肉跑三组输入”正常输入、边界输入、空输入。每次都把中间状态写出来。LRU这种带数据结构的题还要画出当前链表的状态比如头部是谁、尾部是谁、map里有几个键。这个习惯练上两周基本能杜绝“写完不知道代码输出什么”的尴尬。代码题拼的不是谁写得快是拼谁在没有任何工具的环境里还能保持正确。5.3 现象按顺序刷题刷到并发题直接放弃题集通常按知识点顺序排不少人刷到前两章还挺顺利一到并发、JVM这种硬骨头就停下来然后无限期搁置。最后的情况往往是前面语法题练得滚瓜烂熟后面并发题一道没看面试时偏偏就考到了弱项区域。原因是把题集当成了“必须全部读完的书”而不是“按权重分配精力的资源池”。这种心态会放大畏难情绪越难越拖越拖越慌最后干脆假装“先把简单的巩固好”。真相是简单题已经会了再巩固边际收益很低真正拉分的是那些让你想逃的题目。解决方法是回到第2章的分层。先把A层过滤出来再按“每题最多45分钟”限时推进到点没看懂就标黄跳过先保拿得到的分。冷门偏题拿印象分就够了不值得为两成半的内容牺牲八成必考题的熟练度。面试是拿分游戏不是学术研究把时间花在最高回报的地方才是正路。5.4 现象照搬老版本答案和新版本特性对不上题集答案有版本滞后这是几乎每一份静态资料都会有的问题。比如讲HashMap还只说“链表解决哈希冲突”不提JDK 1.8引入的红黑树优化又比如讲线程池还停留在旧版参数行为上。照着背遇到较真的面试官一问到版本差异就容易露馅。原因是答案集锦固化了某个时间点的知识快照而Java本身在持续演进。整理答案的人不可能每出一个新版本就全面更新一遍即使是再认真的资料也会有滞后区域。这不是资料的质量问题而是使用方式问题。解决方法是遇到任何涉及版本的数字都先翻一下对应版本的官方文档或在本机写个小Demo验证以运行结果为准。复习代码题时养成标注JDK版本的习惯这样面试被问到时能明确回答“在JDK 8下是这样的JDK 11里有什么变化”。这种细节在面试中是明显的加分项因为它直接证明你背的不是死答案而是验证过的知识。6. 把题集变成自己的面试系统错题本、复盘与间隔重复基础题122道加代码题19道只是静态素材最终要让它们进入你的面试系统。我的做法是把第2章的自测表升级成错题本但分类方式不是按知识点而是按失分原因概念不清、表达混乱、边界漏判、临场没听懂。每种原因对应不同的补救动作概念不清就回去读答案表达混乱就练四步框架边界漏判就补边界用例临场没听懂就练复述题目。这样分类的价值是你能直接看到自己反复在哪个环节丢分而不是每次都在不同知识点上重新踩坑。每次面试结束后做一次答案反查。把被问倒的题目拿回来找题集里的对应条目找到了就标记“已考薄弱”找不到的新题就补充进自测表。这样用上两三次题集就从122加19变成了122加19加N这个N是你个人独有的增量比任何通用题集都值钱。我认识的一位候选人就是用这个方法三轮面试下来积累了三十多道衍生题后来他再面试时基本没有遇到过完全没准备过的追问方向。代码题我有一个习惯把19道题里的高频几道扩展成带main方法、带测试用例的小Demo。LRU加一个多线程并发读写的测试交替打印加一个“三个线程打印ABC”的变形。扩展过程中你会踩到题集答案里没写的坑比如锁粒度放错位置、sleep放在打印前还是打印后这些坑恰好就是面试官最爱设的小陷阱。把这些坑写进注释里面试时随口讲一句“这里我实际跑过锁粒度放太细会频繁上下文切换”效果比背任何答案都好。间隔重复方面我把自测表里自评分低于3的题做成复习卡片按“1天后、3天后、7天后、14天后”的节奏复习每次只回忆关键词回忆不出来的卡片重新计时。这套方法不复杂但能确保临近面试时最薄弱的题目反而被复习得次数最多。最后说一个我自己的教训我曾经也以为把一份题集背完就是准备充分了直到连续两次面试都在追问环节被同一类问题击穿才发现问题不是“记没记住”而是“有没有把记的东西组织成可表达、可追问、可变形的东西”。从那以后我调整成“背一遍、讲一遍、写一遍、追问一遍”的循环每一轮都比单纯背答案慢但每一轮的增量都是真增量。这套方法同样希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?