十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

2017新奥特Java校招笔试题全解析:从基础到并发,吃透这套就够了

2017新奥特Java校招笔试题全解析:从基础到并发,吃透这套就够了 考过这套题的人应该都有印象2017年新奥特的校招Java笔试题放在当时算是比较“正统”的一套没有什么偏题怪题但覆盖面相当完整从Java基础语法、集合框架、JVM内存、并发编程到简单的算法设计基本把校招Java工程师该有的底子都考了一遍。有意思的是这套题放在今天来看也并不过时里面考的大多数知识点依然是面试场上高频出现的“老八股”这也是我为什么愿意花时间把整套题重新拉出来拆一遍的原因。如果你现在正在准备Java校招或者刚入行想系统梳理一下自己的Java基础这套题的价值在于它帮你划了一条“企业眼中合格校招Java工程师”的能力底线。你不需要刷多少偏题怪题先把这类标准题吃透笔试面试的底气就有一大半了。这篇文章我会顺着这套题的核心考点一条条拆讲清楚每道题背后的考察意图、标准答案、实际应用场景以及我当时做题和后来面别人时总结出来的踩坑点。1. 从一套真题看企业校招Java笔试的出题逻辑拿到一套笔试题先别急着做题先看它想考什么。新奥特这套2017年的题整体结构其实代表了当时大多数互联网和软件公司校招Java工程师的通用出题思路大致可以分为五个维度Java基础语法与面向对象、集合框架与常用API、JVM与内存模型、多线程与并发、算法与编程题。这五个维度并不是随便分配的背后对应的是一个校招Java工程师日常开发中最常打交道的五块内容。比如基础语法和面向对象对应的是你写业务代码时建模和写类的功底集合框架对应的是你处理数据结构和日常存储的基本功JVM对应的是线上问题排查和性能优化的能力多线程对应的是高并发场景下的编码能力算法题则是对逻辑思维和编码基本功的直接考察。把这些维度放到今天来看依然是Java校招笔试的主流结构只不过在细节上会加入一些新的考点比如Lambda表达式、Stream流操作、Spring框架等。为什么企业要用这种“广覆盖、重基础”的出题方式核心原因是校招候选人普遍没有太多实战经验企业很难通过项目经历准确判断一个人的技术水平笔试就成了第一道筛选门槛。基础题能有效过滤掉那些简历写得天花乱坠但实际底子薄弱的人。反过来对候选人来说这套题也给出了一个明确的复习方向你不需要去死磕那些过于冷门的技巧把Java核心基础知识老老实实啃透通过笔试的概率就非常高了。我个人的建议是做这类笔试题时不要只满足于“把答案填对”一定要去追每道题背后的“为什么”。比如题目考了HashMap的底层实现你不光要知道它是由数组加链表组成的还要知道为什么用链表而不是直接用数组什么时候会转成红黑树为什么加载因子默认是0.75。这些追问才是面试官真正想听到的东西。2. 核心考点逐题拆解从出题角度反推知识体系2.1 面向对象基础不只是背概念几乎所有的Java笔试都会考面向对象封装、继承、多态新奥特的题也不例外。这类题看起来简单但想拿高分没那么容易因为概念题最容易暴露“只会背”的毛病。我见过太多候选人能把三大特性背得滚瓜烂熟但一问到“多态在实际项目中怎么用”就卡壳了。其实多态最典型的应用场景就是策略模式和模板方法模式。比如你在写一个支付模块不同的支付方式微信、支付宝、银行卡都实现同一个Payment接口调用方不用关心具体是哪种支付方式直接调接口方法就行。这就是多态在日常开发中最朴素也最实用的体现。笔试中常考的还有一个点是重载和重写的区别。很多人只记得方法签名和返回值的区别但会忽略一个关键细节重写时方法的访问修饰符不能比父类更严格抛出的异常不能比父类更宽泛。这个细节在笔试选择题里经常作为干扰项出现但在实际开发中重写方法时忘记加Override注解才是最常见的问题。这个注解现在IDE都会自动提示加上但它真正的价值在于如果方法签名写错了编译器会直接报错帮你尽早发现问题。说到继承还有一个绕不开的经典问题构造方法能不能被重写答案是不能但构造方法可以被重载。子类构造方法中如果没有显式调用super()编译器会默认插入一个无参的super()调用。所以如果父类没有无参构造方法子类编译就会报错。这个知识点在笔试中经常作为陷阱出现我在面试别人的时候也喜欢用这个问题来考察候选人对Java基础是否真的理解得透彻。2.2 基本数据类型与运算符细节决定成败Java基础部分必考的就是基本数据类型、运算符和表达式。这部分内容看起来是最简单的但恰恰是出错率最高的地方。举个例子i和i的区别相信每个Java开发者都知道i先赋值后自增但放在实际复杂的表达式中很多人就会绕晕。新奥特的题目中就有类似的选择题考察表达式执行的优先级。这里有个我总结的实用技巧笔试遇到不确定的运算符优先级问题千万不要凭记忆硬猜直接在草稿纸上用小括号把运算顺序标出来一步一步推。Java运算符的优先级其实不需要全部记住开发中真正常用的优先级从高到低大概是括号、自增自减、乘除取模、加减、比较、逻辑、三目、赋值。其他的冷门优先级写代码时用小括号明确就好了这也是我们日常编码规范中重点强调的。还有一个必考点是基本数据类型和包装类型的区别。这里有一个高频面试题Integer a 128; Integer b 128; a b 的结果是什么答案是false。但如果你改成两个值都是127结果就变成了true。原因是Integer缓存的范围是-128到127在这个范围内的包装对象是从缓存中取的同一个对象。这个“缓存陷阱”在笔试中出现的频率非常高不仅在Integer中Boolean、Byte、Short、Long都有类似的缓存机制。另外switch语句能用的数据类型也是一个经典考点。Java 7以前只支持int和charJava 7开始支持StringJava 5加入了枚举。但注意long、float、double是不能直接用在switch里的这一点在选择题里常常作为干扰项。2.3 String、StringBuilder、StringBuffer三兄弟这套题里还有一类出现率极高的题型就围着String家族打转。三个类都能处理字符串但底层设计逻辑完全不同这背后就是一个典型的“场景决定选择”问题。先说String。String对象不可变每次拼接字符串都会产生新的对象所以大量循环拼接时性能会非常差。String的不可变性带来一个好处是线程安全和字符串常量池缓存这也是为什么String能被用作HashMap的key。简单说String是牺牲性能换来了安全性和缓存收益。StringBuffer是线程安全的可变字符串类它的方法都加了synchronized锁所以在单线程场景下会有不必要的性能开销。而StringBuilder是线程不安全的可变字符串类但它反而成为开发中的首选因为绝大多数场景下我们拼接字符串都在单线程环境中进行。这里有一个很关键的问题为什么现在开发中特别是JDK 8之后的版本字符串拼接用“”号其实也挺快因为javac编译时如果检测到字符串变量是通过加号拼接会自动用StringBuilder优化。但这里有个前提就是拼接操作要在一条语句内完成。如果是循环体内反复拼接编译器没法优化每次循环都会创建新的StringBuilder对象性能依然很差。所以正确的做法是循环外层手动创建StringBuilder循环体内用append方法。2.4 集合框架从“会用”到“懂原理”集合框架是Java笔试的重头戏也是拿分和拉开差距的关键部分。新奥特的考题几乎覆盖了集合框架的各个核心类所以我建议你把这部分当作复习的重心。ArrayList和LinkedList的区别是基础中的基础。ArrayList底层是动态数组查询快、增删慢尾部增删除外LinkedList底层是双向链表增删快、查询慢。但这里有个容易忽略的细节LinkedList的增删快并不是绝对的。如果删的是中间位置的元素LinkedList依然需要从头遍历找到那个位置时间复杂度是O(n)而ArrayList如果在尾部删除时间复杂度是O(1)。所以实际开发中ArrayList的适用面其实比LinkedList广得多。HashMap是集合框架中最核心的内容也是面试官最爱深挖的点。从JDK 1.8开始HashMap底层由“数组链表红黑树”组成链表长度超过8且数组长度大于64时链表会转成红黑树。为什么要转红黑树因为当链表很长时查询效率退化成O(n)红黑树能把查询效率保持在对数级别。但转树也有代价树节点比链表节点占用的内存更大所以不是一超过8就转还要看数组长度。HashMap的默认加载因子是0.75这个值其实是时间和空间的一个平衡点。加载因子太小比如0.5数组的利用率就低浪费空间加载因子太大比如1.0数组容易堆积链表查询效率变差。0.75是一个经过数学推导和工程验证的经验值。HashSet和TreeSet也是一个考点。HashSet的底层是HashMap只用了keyTreeSet的底层是TreeMap支持排序但放入的元素必须实现Comparable接口或者在构造TreeSet时传入Comparator。这里在实际开发中有一个常见报错向TreeSet里加入元素没实现Comparable接口运行时报ClassCastException。面试时问到这个点可以把这个具体场景说出来会比较有说服力。HashMap和Hashtable的区别同样高频。Hashtable是线程安全的所有方法都加了synchronized但正因为如此单线程下性能很差HashMap不是线程安全的但在单线程下性能很好。Hashtable不允许key或value为null而HashMap允许一个null key和多个null value。工程上现在基本不用Hashtable了并发场景直接用ConcurrentHashMap。2.5 JVM内存模型笔试答对面试说清JVM部分是Java笔试中技术含量最高的一块新奥特的题涉及了内存区域划分、垃圾回收和内存溢出这几个典型考点。JVM运行时数据区分为线程共享和线程私有两大部分。线程共享的区域是堆和方法区在JDK 1.8之后方法区被元空间取代使用本地内存线程私有的区域是虚拟机栈、本地方法栈和程序计数器。这里有个高频题目哪个区域会抛出OutOfMemoryError堆会方法区元空间会虚拟机栈会栈深度不足时抛出StackOverflowError或OOM程序计数器不会。垃圾回收这个考点我最怕听到的答案就是“JVM会自动帮我们回收垃圾”一句话就结束了。这个点至少要理解回收器判断“垃圾”的算法逻辑。引用计数法和可达性分析算法是最基础的两种判断方式现代JVM用的是可达性分析从GC Roots出发遍历所有引用链没有被引用到的对象就是垃圾。GC Roots包括虚拟机栈中引用的对象、方法区中静态属性引用的对象、常量引用的对象、本地方法栈中JNI引用的对象。垃圾回收算法也有几个经典说头。标记-清除算法是基础会产生大量内存碎片复制算法将内存划分为两块只用一块GC时把存活对象复制到另一块适合存活率低的年轻代标记-整理算法先标记存活对象然后让所有存活对象向一端移动适合存活率高的老年代三种算法组合起来对应了分代收集理论这也是为什么我们把堆分成年轻代和老年代来管理。内存溢出和内存泄漏的区别也是笔试选择题的常客。内存溢出是内存真的不够用了堆空间耗尽内存泄漏是对象用完后没有被释放一直占据内存时间长了最终会导致内存溢出。典型的内存泄漏场景包括静态集合类持有对象、未关闭的数据库连接、非静态内部类持有外部类的引用等。排查内存泄漏的常规手段是生成堆转储文件然后用MAT或VisualVM分析。2.6 多线程与并发校招Java笔试的分水岭多线程这块新奥特2017年的题放在当时算是有一定深度的因为并发编程对校招生来说确实是个分水岭。我现在带校招生第一周就让他们看线程安全的几个基础问题因为这部分在实际工作中太常遇到了。创建线程的方式是一个基础考点。继承Thread类、实现Runnable接口、实现Callable接口、使用线程池这四种方式各有适用场景。其中Callable和Runnable最大的区别是Callable有返回值并且能抛异常所以它更适合需要异步获取结果的场景。实际开发中我强烈建议直接用线程池不要手动new Thread——线程的创建和销毁成本很高而且无限制创建线程会拖垮系统。线程池是并发编程里最实用的一个知识点也是面试官最爱深挖的地方。ThreadPoolExecutor的核心参数有七个核心线程数、最大线程数、空闲存活时间、存活时间单位、任务队列、线程工厂、拒绝策略。很多人能背出这七个参数但一问到“核心线程数是1最大线程数是3队列容量是10此时同时来100个任务会发生什么”就完全不知所措了。这里我展开说一下上面的过程先来第一个任务会创建核心线程去执行核心线程满了后续任务会放进队列队列满了才会创建非核心线程最多到最大线程数最大线程数也满了队列也满了就会触发拒绝策略。这个执行顺序非常关键笔试和面试中都反复考到。默认的拒绝策略是AbortPolicy直接抛RejectedExecutionException但在一些业务场景下会使用CallerRunsPolicy也就是让提交任务的线程自己去执行这个任务这样不但不会丢任务还能起到天然的限流效果。wait和sleep的区别也是高频考点。wait是Object类的方法调用后会释放锁只能用在同步代码块中sleep是Thread类的静态方法调用后不会释放锁。理解了这个区别就很好理解为什么生产环境中消费者线程要用wait而不是sleep来做阻塞等待了。还有synchronized和Lock的区别。synchronized是JVM层面的关键字异常时会自动释放锁Lock是API层面的接口必须手动释放锁但它的灵活性更高支持尝试非阻塞获取锁、支持中断响应、支持公平锁。在低竞争场景下synchronized的性能并不比Lock差JVM还在不断优化它引入了偏向锁和轻量级锁。2.7 常见算法题冒泡、快排和查找的战术价值新奥特这套题包含常见排序和查找算法比如冒泡排序和快速排序这也是Java校招笔试中很典型的编程题。这类题不是考你背代码而是检验你的逻辑分析能力、代码组织能力和边界条件的考虑。冒泡排序是最基础的排序算法核心思想是重复遍历数组每次把相邻的两个元素进行比较如果顺序不对就交换。每一轮遍历之后最大的元素就会“浮”到数组末尾。冒泡排序的时间复杂度是O(n²)空间复杂度是O(1)它是稳定排序。说句实在话冒泡排序在实际开发中基本不会用它考察的就是你对循环嵌套和最基础的数组操作是否熟练。快速排序则要更实用一些。它的核心思想是分治选择一个基准值把数组分成小于基准和大于基准的两部分然后分别对两部分递归排序。快排的平均时间复杂度是O(n log n)但最坏情况下会退化到O(n²)为了避免这种情况通常会采用随机选取基准值或三数取中的策略。这是笔试中常考的一个优化点答出来会给你加分不少。排序之外二分查找也是高频考点但它有一个容易被忽视的前提数组必须是有序的否则结果无意义。二分查找的时间复杂度是O(log n)每次比较都能排除一半的数据这个思路在刷题和实际开发中都非常值得借鉴。我给大家一个建议笔试中如果时间紧张先写能跑通的版本再逐步优化。例如要求实现一个排序算法先把冒泡写出来保证正确性时间有余就去写快排。千万不要卡在快排上想半天最后连基础版本都没交上去。3. 实操复盘按这套真题标准如何搭建自己的Java复习路线3.1 先建知识地图再逐点攻破做完这套题之后有一个重要的动作把自己的错题和不确定的题目汇总起来形成一份自己的知识地图。Java校招笔试的范围虽然广但核心的考点其实是有限的用思维导图软件过一遍基础语法、集合、JVM、并发、IO、网络编程、数据库、Spring基本上就能覆盖90%以上的笔试题目。这里我给一个相对实用的复习优先级建议。第一优先级是面向对象基础和集合框架这两块是Java笔试中出现频次最高、出题方式最灵活的部分。第二优先级是JVM内存和多线程这部分是笔试拉开差距的关键。第三优先级是算法题不需要刷太多难题把冒泡、快排、二分、链表反转等基础算法写得滚瓜烂熟就够了。第四优先级是框架和数据库这部分笔试题不多但在技术面和项目面中是重点。根据这套优先级我建议把复习周期安排为3到4周第一周主攻Java基础语法、面向对象、异常处理第二周主攻集合框架和常用类库彻底弄清楚ArrayList、LinkedList、HashMap、TreeMap等底层实现第三周主攻JVM内存模型、垃圾回收、多线程并发第四周刷题集中做历年的Java校招笔试真题保持手感。3.2 一个高效的错题整理模板做笔试题不能光做题不整理那样等于白做。我习惯用一个很简单的错题整理模板每个记录包含四要素题目、我的答案、正确答案、错误原因。错题不要按来源划分而是按知识点划分这样复习的时候可以一目了然。比如你在HashMap的题目上反复出错就可以把关于HashMap的错题全部归在一起你会发现自己的问题集中在某个环节比如扩容机制、树化条件或者加载因子。找到共性问题再去集中复习那一个知识点效率会高很多。我也是在带新人后才发现很多应届生刷了几百道题但脑子里面的知识是碎片化的没有形成体系一到面试现场稍微一变型就答不上来。体系化的知识才是真正属于你的东西。3.3 从笔试到面试这道题的答案还能怎么延伸新奥特的题虽然属于“正统”风格但这套题背后的知识点在面试环节里会被问到很多变形和延伸题。你在准备笔试的时候不妨多想想这道题的答案如果面试官接着追问我还接得住吗举个例子题目考HashMap的实现原理面试官可能会接着问HashMap在多线程环境下会怎样答案不是简单的“线程不安全”五个字你要能说出具体问题JDK 7中并发环境下扩容时可能出现环形链表导致死循环JDK 8修复了死循环问题但并发put仍然可能导致数据丢失。再往下追问就需要你引出ConcurrentHashMap的实现原理。另一个常见的延伸是如果题目考了String的不可变性面试官会接着问String对象为什么设计成不可变这时你需要从几个角度回答安全性和线程安全、字符串常量池的缓存、哈希计算依赖。在写网络请求时参数拼接后用String存储也是基于这个原因——传参过程中对象不会被意外修改。我在带人的时候经常建议他们用“三层法”去学习每个知识点第一层是知道是什么能背出定义第二层是知道为什么能解释底层原理和设计初衷第三层是知道怎么用能在实际项目或场景中应用它。对校招笔试来说第一层和第二层足够应对大多数题目但要通过面试拿到offer三层都必须到位。4. 当年踩过的坑校招Java编程题与选择题的答题细节4.1 选择题的陷阱套路这套新奥特的笔试题里选择题占了很大比例而且选择题往往暗藏陷阱。我在做题和阅卷时都积攒了不少经验这里挑几个典型的套路说一下。最常见的一个陷阱是在集合相关的题目中刻意混淆“接口”和“类”。比如选项里出现“Collection是一个类”很多基础不扎实的人一看顺眼就选了。实际上Collection是接口Collections从最底层剥离一个是接口一个是静态工具类。这种题型考察的并不难主要就是在提醒你平时学习时不要只看类名要准确区分接口、类、抽象类的层级关系。第二个陷阱是修饰符权限范围。Java有四种访问权限public、protected、默认、private范围从大到小。选择题经常会出“protected访问权限的含义”干扰项会写成“同一个包内可见”或“子类可访问但不能跨包”。标准答案其实是“同一个包内可见且不同包的子类可以访问”。这个细节非常容易踩坑。第三个陷阱是在异常处理相关题目中混淆受检异常和非受检异常。受检异常必须显式处理或声明抛出比如IOException、SQLException非受检异常是运行时异常比如NullPointerException、ArrayIndexOutOfBoundsException编码时可以不显式处理。题目问“下列哪个异常属于运行时异常”很多人会把SQLException选进去这就是典型的混淆。4.2 编程题的答题策略和规范如果笔试包含手写代码环节答题策略比代码本身更重要。先说一下整体节奏拿到编程题先别急着写代码花一两分钟把题目读清楚确认输入输出格式再看时间和空间复杂度的要求。接下来先说思路说清楚是暴力解还是优化解再动手写。即使是纸笔答题也要保持代码规范。变量名要有意义缩进要清晰每完成一个逻辑就适当留个空行。笔试虽然不像代码评审那样严格但干净的代码风格绝对能给阅卷官留下好印象。记住你写的每一行代码都代表着你在团队协作中的代码习惯。碰到不会的题目一定不要留空白。写一个暴力解法或者用文字描述你的解题思路都能拿到部分分值。我见过不少候选人题目不难但因为卡在某一个细节上死磕导致后面简单的题目都没时间写这是最遗憾的事情。编程题是重策略的不是重硬拼的先把能拿的分拿到手再去争取难题的分数。4.3 时间分配技巧标准化考试思维笔试的时间分配至关重要。以一套120分钟的试卷为例我会把时间按照4:5:1的比例分配前面40分钟左右完成选择题和填空题后面60分钟主攻编程题和大题最后20分钟检查。前面基础题部分不能拖延因为编程题很容易超出预期时间。还有一个经验值得特别强调很多校招笔试题量都不小如果你在某道选择题上卡了超过3分钟建议先随便选一个答案并跳过做个标记一道选择题的分值无法匹配你在它身上花的时间。笔试通过的关键在于总分离线而不是单题满分。还有一点关于题目顺序不要跟题目顺序硬磕可以先花30秒把整张试卷扫一遍看看题型和题量从自己最有把握的部分开始做。这既能尽快进入状态也能确保最简单的分数先落袋为安。5. 2017年的题放在今天还能怎么用我知道现在市面上Java面试的“行情”已经变了好多各种框架、分布式、微服务、云原生不胜枚举很多人在准备校招时容易陷入“什么都想学、什么都学不深”的状态。但你看新奥特这套2017年的卷子你会发一个规律不管行业怎么变基础永远是企业考察的第一道门槛。我自己在面试时也持同样的态度。一个人能不能写业务代码看项目经历可以看出来但这个人往上走有没有潜力大概率还是看基础基本功。JVM内存模型、并发编程思想、集合底层原理、代码设计原则这些底层能力是不会随着框架更迭而过时的。你在Spring Boot里写的每一个Controller最终还是在调用Java基础语法和集合操作。你在排查线上性能问题时最终还是要靠JVM的知识支撑起来。所以我的建议是这套题的复习价值不仅在于应付新奥特的校招更在于它帮你建立了一套“不动摇的根基”。你的技术栈可以换框架可以换语言都可以换但设计模式、算法思维、底层原理这些核心素养是你走技术这条路的护城河。我在带校招新人时经常说一句话面试造火箭工作拧螺丝这是事实。但“拧螺丝”的人如果懂一点“火箭原理”他拧螺丝的角度都会不一样。Java基础就是那个“火箭原理”新奥特这套题就是帮你检验自己火箭原理掌握程度的试金石。6. 写在最后的个人复盘建议复盘是个好习惯但复盘本身也讲究方法。做题之后我建议你把错题对应的知识点单独列出来不要只记答案。举个具体操作办法每整理一个错题就顺手给自己出一道“变形题”问问自己能不能答上来。比如原题考的ArrayList的扩容机制你就问自己如果我用LinkedList替代性能瓶颈会出现在哪里这样的复盘模式把一个知识点的理解真正内化掉了。至于面试前几天不要再刷难题了。把错题集和知识地图过一遍把HashMap、JVM、线程池、String这几个高频考点复习到保持好的状态比临时抱佛脚刷一堆偏题更有用。笔试考验的不仅是知识积累还有考试状态和心态睡好觉也是备战的必要环节。最后再分享一个小技巧这套新奥特的题你现在可以不用分年份看待它。2017年和2025年校招Java笔试的核心考点变化并不大做题的核心目标不是应付某一家公司而是培养“用工程师思维去分析问题”的习惯。你每做一道Java题都逼自己去理解底层设计的原因这个过程本身就是在为未来的职业生涯铺路。把这点想清楚了做任何一道题都不会是浪费时间。
返回列表