Java基础面试题122道:考点拆解与备考实战指南
最近后台一直有人问我要Java面试题尤其是基础部分。说实话网上Java面试题一抓一大把但大部分要么是零散的知识点罗列要么是直接照着别人的博客抄连答案错没错都不管。我整理这份“基础题122道”其实是把过去几年面试别人、被别人面试、以及帮朋友辅导时反复出现的高频考点做了一次系统归拢。本文不打算把122道题一股脑贴出来那没有意义我想把这份题库背后的设题逻辑、核心考点拆解、备考方法和踩坑经验讲清楚你拿到这份清单之后能真正用起来。1. 这122道基础题是怎么整理出来的——先聊聊设题逻辑1.1 基础题在Java面试中的真实分量很多人有一个误区觉得Java面试就是拼框架、拼项目、拼算法基础题只是走个过场。实际我面过的人里挂掉最多的恰恰是基础题环节。尤其是三年以内的开发岗面试官不可能拿高并发架构和分布式事务来压你反而会从JVM内存、集合源码、线程状态这些“最没技术含量”的问题切入探你的底子。基础题答得是否流畅、是否有深度直接决定了面试官对你技术水平的初始判断。我见过一个候选人简历上写着熟悉Spring Cloud微服务治理结果我问“HashMap在JDK 8里什么时候转红黑树”他支支吾吾说“好像是链表太长”。这就很尴尬了。项目经验可以包装简历技能可以注水但基础题一问一个准根本装不了。所以我认为基础题不是面试的“开胃菜”而是“照妖镜”。1.2 考官出基础题的三个层次记忆、理解、应用我在整理这122道题时刻意按照考官的出题逻辑做了分层。第一层是记忆类题目比如“Java的基本数据类型有哪些”“String和StringBuilder的区别”这类题考察你有没有系统学过Java属于送分题但送分题也经常有人答不完整比如基本数据类型漏掉char或者boolean的占用位数记错。第二层是理解类题目比如“HashMap的put方法流程是什么”“synchronized和ReentrantLock的区别有哪些”这类题要求你能讲清楚底层原理和设计思想。第三层是应用类题目比如“什么场景下会内存溢出怎么排查”“线程池的拒绝策略怎么选”这类题考察你在实际项目中能不能把基础知识用起来。三个层次逐级递进只靠背答案是过不了理解层和应用层的。1.3 122道题的分类框架与考点分布我在整理时把122道题分成了七个大块Java基础语法、面向对象、集合框架、并发编程、JVM与内存、IO与异常、新特性与工具。这个分类基本对应了绝大多数Java岗位JD里“熟悉Java核心基础”的要求。其中集合、并发、JVM三个板块占比最高加起来超过一半这跟实际面试的考察频率是一致的。如果你手里也有一份类似题库我建议你做的第一件事不是开始背题而是先对照这个分类框架自查一遍看自己哪个板块最薄弱。比如你集合框架题能答对八成但并发编程题一遇状态机就头大那你的复习优先级就很清楚——先攻并发而不是从头到尾平均用力。这份122道题的价值不在于“多”而在于让你通过它完成一次完整的知识体系扫描。2. 核心考点拆解之一JVM内存与类加载机制2.1 运行时数据区域别背八股要能画图JVM内存模型是基础题里的重头戏几乎必考。但很多人背得滚瓜烂熟却经不起追问。面试官问“Java内存区域怎么划分”你要是只答出“堆、栈、方法区”三个词大概率会被追问程序计数器是干什么的本地方法栈和虚拟机栈什么区别直接内存属于JVM内存吗我记得刚入行时也被问懵过。后来我自己画了不下五遍内存结构图才真正把这块理清楚。堆存放对象实例虚拟机栈存放栈帧局部变量表、操作数栈、动态链接、方法出口方法区在JDK 8里换成了元空间Metaspace使用的是本地内存。程序计数器是线程私有的记录当前线程执行的字节码行号只有执行native方法时才是未定义的。这些细节你得能边画图边讲而不是靠背诵。2.2 垃圾收集与常用回收器GC这块是JVM考点的第二座大山。基础题一般会问到“如何判断对象可以被回收”“常见的垃圾收集器有哪些”。判断对象是否可回收主流答案就是可达性分析从GC Roots出发遍历对象图不可达的对象标记为可回收。GC Roots包括虚拟机栈中引用的对象、静态属性引用的对象、常量引用的对象、本地方法栈中JNI引用的对象。收藏器方面面试高频是CMS和G1的区别以及JDK 11之后默认的ZGC。CMS的缺点是碎片化和并发阶段CPU敏感G1用Region划分堆内存可预测停顿时间。你要是能主动提一句“G1在JDK 9以后成为默认垃圾收集器”面试官会认为你有持续跟进的习惯。另外需要记住的是对象分配优先在Eden区大对象直接进老年代-Xms和-Xmx建议设为相同值避免堆扩容抖动——这些细节都是我实际排查线上问题时验证过的。2.3 类加载机制和双亲委派模型类加载机制也是基础题常客典型问法是“什么是双亲委派模型”“为什么需要双亲委派”。回答这个问题不要只说“先让父加载器加载不行自己再加载”要讲清楚这样做的目的防止核心类库被篡改。比如你自定义一个java.lang.String如果不走双亲委派应用加载器先加载了你的类那整个JVM的字符串操作就乱了。双亲委派保证核心类库只能由引导类加载器加载。这里建议大家补充一个知识点类加载的三个过程是加载、连接验证、准备、解析、初始化。很多人会把“加载”和“初始化”混为一谈。面试官问到“静态代码块什么时候执行”理解类初始化阶段才能真正答对。还有一点打破双亲委派的典型场景是Tomcat的WebAppClassLoader它为了每个Web应用隔离jar包会优先自己加载这是面试加分项。2.4 OOM场景与排查思路基础题考OOM通常会问“哪些区域可能发生OutOfMemoryError”。堆内存不足是最常见的对应java.lang.OutOfMemoryError: Java heap space。元空间不足会报Metaspace错误。栈溢出则是StackOverflowError深层递归调用触发。除了说出这些错误类型更重要的是说出排查思路——用jmap dump堆转储配合MAT或者JProfiler分析大对象然后定位到代码行。我自己排查过的一个典型案例一个定时任务每天批量处理数据时经常OOMdump下来一看是某个工具类里静态Map缓存了全量用户数据只增不减。这种问题靠调大堆内存是治标不治本真正的解法是换成带过期策略的本地缓存或引入Redis。把这个案例讲给面试官听比单纯背诵“堆内存溢出可以调大-Xmx”有说服力得多。3. 核心考点拆解之二集合框架里的数据结构博弈3.1 HashMap从put到扩容的完整链路HashMap是Java面试的神级考点没有之一。我这份122道题里光是围绕HashMap展开的变体题就有十几道。最核心的主线问题就是一个key-value被put进HashMap之后到底经历了什么。正确流程是先对key计算hash值做一次高低位异或扰动然后(n-1)hash定位到数组下标位置如果该位置为空直接放入如果不为空遍历链表或红黑树比对key的equals方法相同则覆盖不同则尾插进入。关于扩容要记住默认初始容量16、负载因子0.75、单链表长度到8且数组长度到64时转红黑树这三个阈值。为什么是0.75这是空间和时间的一个折中。为什么树化是8因为理想情况下hash分布均匀时链表长度到8的概率极低还不到千万分之一所以8是泊松分布的参考值。能把这个数学背景讲出来你就不只是“背过答案”是真的理解了设计者的意图。3.2 ArrayList与LinkedList的取舍之道ArrayList和LinkedList的对比也是基础题高频。标准答案是ArrayList基于动态数组随机访问快插入删除慢涉及元素搬移LinkedList基于双向链表插入删除快随机访问慢。但这个答案有个陷阱——实际项目中LinkedList的插入删除“快”是有条件的。如果你在List中间频繁插入删除LinkedList确实有优势因为它只需要改前后节点的指针但如果你是在尾部追加元素ArrayList通常更快因为ArrayList尾插是直接赋值摊销时间复杂度O(1)而LinkedList每次都要new一个节点。另一个衍生考点是ArrayList的扩容机制。默认初始容量10每次扩容为原来的1.5倍oldCapacity (oldCapacity 1)扩容后需要把旧数组复制到新数组这是典型的空间换时间取舍。我面试时会追问“如果在循环里反复add十万个元素会扩容多少次”很多人答不上来。算一下容量序列是10、15、22、33、49……大概会扩容17次左右每次都有数组拷贝开销。这也是为什么能预估数据量时建议直接new ArrayList(expectedSize)的原因。3.3 集合类的线程安全与并发容器集合线程安全这块我会把题目的层次拉开。基础题会问“ArrayList是线程安全的吗”然后延伸到Vector和Collections.synchronizedList、CopyOnWriteArrayList这三者的关系。Vector是JDK 1.0的老古董方法加了synchronized但性能差。Collections.synchronizedList通过包装器给每个方法加锁但复合操作仍然不安全。CopyOnWriteArrayList是读写分离思路读不加锁写时复制一份新数组适合读多写少的场景。还有一个高频点是ConcurrentHashMap。面试官喜欢问“ConcurrentHashMap为什么比Hashtable效率高”你要能答出Hashtable是锁整个表而ConcurrentHashMap在JDK 7用Segment分段锁JDK 8改为CAS加synchronized锁链表头节点锁粒度更细并发度更高。能讲出JDK 7到JDK 8的变化说明你关注过演进基础题的加分项往往就在这些细节里。4. 核心考点拆解之三并发编程的原子性、可见性、有序性4.1 线程创建方式与生命周期并发编程在Java基础面试里占据绝对主力位置。最基础的题目是“创建线程有几种方式”。标准答案是四种继承Thread类、实现Runnable接口、实现Callable接口配合FutureTask、使用线程池。但只答这四种只能算及格要加分就得接着说继承Thread和实现Runnable本质上没有区别因为Thread本身也实现了RunnableCallable跟Runnable比多了返回值可以抛出受检异常线程池方式本质上还是前三种的封装但好处是线程复用避免频繁创建销毁。线程的状态是另一个必考点NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。我面试时会让候选人画状态转换图重点看两个地方一是wait()进入WAITING后notify()唤醒进入的是Runnable还是Blocked正确答案是Runnable二是sleep()和wait()的区别sleep不释放锁wait释放锁——这个问题不知道绊倒了多少人。4.2 synchronized与Lock的底层博弈synchronized和ReentrantLock的对比属于理解层题目光答“一个是关键字一个是类”肯定不行。要往深了讲synchronized经过JDK 6的锁升级偏向锁→轻量级锁→重量级锁后性能已经不输Lock大多数场景下官方都推荐用synchronized。但Lock有自己的独门绝技可中断锁、可超时获取锁tryLock(timeout)、公平锁、多个条件队列Condition这些是synchronized不具备的。还有他们的底层原理synchronized基于Monitor监视器锁通过字节码指令monitorenter和monitorexit实现。ReentrantLock基于AQSAbstractQueuedSynchronizer通过volatile的state变量加CLH队列实现。面试官如果追到AQS级别你至少要把“独占模式”“共享模式”“state状态的CAS操作”这三个关键词答出来。这块内容偏深但基础题里出现它的概率并不低值得好好准备。4.3 volatile、CAS与AQSvolatile是并发基础题里最容易“答而不懂”的一个点。很多人能背出“保证可见性不保证原子性”但一问“为什么不能保证原子性”就卡住了。volatile的语义是写一个volatile变量会立即刷新到主内存读一个volatile变量会从主内存重新读取这就是可见性但它没有锁对count这种读改写操作多个线程的指令仍然会交错执行所以不保证原子性。还有一个考点是volatile会禁止指令重排也就是有序性典型应用是单例模式的双重检查锁中的volatile修饰单例对象。CAS是并发编程的基石全称Compare And Swap比较并交换。你要能解释它的三个操作数内存位置V、预期原值A、新值B只有V的值等于A时才用B更新V否则什么都不做。CAS最大的缺点是ABA问题解决思路是加上版本号Java里AtomicStampedReference就是干这个的。面试时主动提ABA问题会让面试官觉得你的并发基础不是背出来的。4.4 线程池的七大参数与拒绝策略线程池是应用题的高频考法。基础题一般是问“线程池有哪些参数”但我会建议你把七个参数背到滚瓜烂熟核心线程数、最大线程数、空闲线程存活时间、存活时间单位、任务队列、线程工厂、拒绝策略。然后要能讲出执行流程提交任务后先判断核心线程是否满没满就创建线程执行满了就进队列等待队列满了再判断最大线程数没满就创建临时线程都满了就执行拒绝策略。拒绝策略有四种AbortPolicy直接抛异常默认、CallerRunsPolicy调用者线程自己执行、DiscardPolicy直接丢弃、DiscardOldestPolicy丢弃最旧的任务。这里我要提醒一个实战经验线上环境建议自定义拒绝策略至少要把任务信息打日志否则用DiscardPolicy任务被丢了你都不知道。还有核心线程数怎么设CPU密集型的设为CPU核数1IO密集型的设为2 * CPU核数这是经验值但真实场景还要结合压测来调。5. 核心考点拆解之四异常、反射、IO与泛型的隐藏联系5.1 异常体系受检异常与非受检异常怎么区分异常在基础题里出现频率不算最高但属于送分送得最干脆的模块。Java的异常体系以Throwable为根下面分Error和Exception。Error是JVM层面的严重问题比如OutOfMemoryError、StackOverflowError程序无法处理也不应该处理。Exception下面又分受检异常Checked Exception和非受检异常RuntimeException。受检异常必须在代码里显式捕获或抛出比如IOException、SQLException编译期就强制检查。非受检异常包括NullPointerException、ArithmeticException、ClassCastException等编译期不强制处理。面试官喜欢问“什么时候用受检、什么时候用非受检”我的经验是调用方能合理恢复的用受检比如文件不存在可以提示用户换个路径而编程错误导致的用非受检比如空指针和数组越界这些应该通过修代码解决。还有try-with-resources这个JDK 7特性能自动关闭实现了AutoCloseable的资源比如流和数据库连接这也是一个容易考到的细节。5.2 反射机制的经典应用场景反射是Java动态特性的基石也是很多框架底层的核心。基础题问法是“什么是反射能做什么”进阶一点会问“反射有哪些应用场景”。标准答案是在运行时获取类的完整结构信息类名、方法、字段、注解并可以动态调用方法和操作属性。坏处也要能说出来性能开销大比直接调用慢几个数量级、破坏封装性、增加代码复杂度。反射在现实中的经典应用包括Spring的IOC容器通过反射创建Bean实例MyBatis通过反射把数据库字段映射到实体类属性还有各种ORM框架。如果你想在答案里加点“有经验”的东西就说反射配合注解做字段校验器——这是很多公司实际在做的事情。我做过一个项目就是定义NotNull、Length(max 50)这类注解然后用反射扫描实体字段做参数校验框架代码量很小但全项目通用这就是反射能力的最佳展示。5.3 泛型擦除为什么运行时拿不到ListString泛型是Java面试里比较“烧脑”的基础考点。核心知识点是Java的泛型是编译期类型检查运行时泛型信息会被擦除。所以ListString和ListInteger在运行时的Class对象是同一个ArrayList.class你不能通过反射拿到ListString的String这个类型参数。这个设计是为了兼容JDK 1.5之前的老代码。泛型擦除带来的常见面试题包括为什么不能创建泛型数组new T[10]是不合法的为什么静态方法不能访问类级泛型参数以及什么是通配符上下界。上下界这个点经常考? extends T是上界通配符表示T或T的子类只能读不能写? super T是下界通配符表示T或T的父类只能写不能读。记住口诀“PECSProducer ExtendsConsumer Super”这是Effective Java里的经典总结。5.4 IO模型BIO、NIO、AIO到底是什么IO这块基础题喜欢问“BIO、NIO、AIO的区别”。BIO是同步阻塞IO一个连接一个线程连接空闲时线程也在阻塞等待资源浪费严重。NIO是同步非阻塞IO基于通道和缓冲区配合Selector选择器可以用一个线程管理多个连接。AIO是异步非阻塞IO发起IO操作后直接返回完成后由操作系统通知回调。面试官在这里最想听到的不是三个缩写而是你用过什么。多数候选人会聊Netty这没问题但你要能讲出NIO的三件套Channel通道双向的、Buffer缓冲区读写都要经过它、Selector选择器注册感兴趣的事件轮询就绪事件。再深入一点IO多路复用有select、poll、epoll三档演进epoll用红黑树加事件驱动是Linux下性能最高的模型。能把这个链路讲清楚说明你不只是背概念是真的理解。6. 122道题之外的备考建议与踩坑记录6.1 刷题的正确姿势先分类、再输出、后复盘一份122道题的清单拿在手里最忌讳的是从头到尾背一遍。我推荐的刷法分三步。第一步是分类先按我前面说的七个板块把题目归类统计每个板块的题量找出自己的薄弱区。第二步是输出每道题别只在脑子里过要开口讲出来或者用文字写一遍。输出过程会逼你把模糊的地方暴露出来讲不顺畅的地方就是你还没真正理解的地方。第三步是复盘隔两三天重新讲一遍错题和卡壳题直到流畅为止。我见过太多人刷题的方式是“看答案记住了下一道”这就是无效刷题。你面试时面对的是动态追问不是按原题背诵如果没把原理内化成自己的表达换个问法就露馅。我建议你每道题准备30秒到一分钟的版本再准备一个三分钟的扩展版本前者用于快答后者用于应对追问双版本打法反而能帮你把知识点理得更透。6.2 基础题和框架题的时间怎么安排看热词就能发现现在Java面试题里MyBatis、Redis、Kafka、Spring Boot这些框架和中间件占比非常高。很多人就慌了觉得基础题是不是没那么重要了。我的观点是基础题和框架题不是二选一而是前后关系。框架本身就是建立在基础之上的MyBatis的Mapper代理用到了动态代理机制Spring的声明式事务用到了动态代理和AOPRedis分布式锁的原子性问题用到了Java并发知识Kafka消费者组的再平衡也和线程模型有关。我给一个时间配比建议如果距离面试还有一个月前两周主攻本文章覆盖的Java基础核心第三周把集合、并发、JVM三大块结合源码做深度阅读最后一周围绕MyBatis、Redis、Spring Boot做结合每个框架顺手准备几个“底层原理”问题。热词里还有Linux、SQL、前端Vue的面试题这些通常是不同岗位的要求如果你投的是Java后端开发主战场还是Java基础和中间件Linux和SQL可以安排为辅助内容但不能反客为主。6.3 高频失分点与面试表达技巧最后分享几个真实的失分点。第一个是“答案太长没有重点”一道满分为止的简述题硬是讲成五分钟的演讲。面试官追问时再往深里展开不追问就果断收住这是表达节奏问题。第二个是“不加限定地使用绝对化词语”比如“线程池一定是这个参数”“G1一定比CMS好”工程上很少有绝对使用“大多数场景”“默认情况下”这种限定词显得你更有实践经验。第三个失分点是“只答是什么不答为什么”。举例来说面试官问“HashMap默认容量为什么是16”你要是只说“不多不少就是为了均匀分布”就不够能补充“16是2的4次方方便hash值通过位运算取模同时兼顾了内存占用和hash散列效果”才算答到位。第四个容易翻车的是“把别人博客的结论当自己的经验”比如网上说“LinkedList插入比ArrayList快”就直接背我前面已经说了这个结论是有前提的你得能区分场景。我在实际面试别人的过程中最看重的就是“能不能把原理讲得让人听懂”。一道Java基础题候选人能结合到自己的项目场景哪怕场景很小也比把源码默写一遍有说服力。所以这份122道题的最终用法不应该是背完就完而是每道题都去想想我之前的项目里哪里遇到了这个问题我当时的处理方式是什么现在回头看有没有更好的方案。把题库当成一面镜子照出自己的短板和盲区这才是它最大的价值。