
1. 为什么一份2018年的老卷子放到今天依然值得逐题拆解先说一个可能颠覆你认知的结论Java工程师校招笔试这六年核心考点的变动幅度小到可以忽略不计。网易2018校园招聘Java工程师笔试卷放在各种刷题平台上已经算“老古董”了但如果你真的找一套来完整做一遍会发现里面考的东西和今年各大厂的校招笔试几乎没有本质区别还是那批有序集合、并发工具、JVM内存模型、类加载机制、手写排序和链表。语言特性偶尔换个问法底层的原理纹丝不动。这篇文章想做的不是把某套题的参考答案念一遍——那种东西你在网上随便就能搜到背完第二天就忘。我更想把它当成一份“校招Java考纲切片”从题型结构、命题规律、高频陷阱、手写代码的解题套路几个维度拆开讲让你知道为什么会这么考、错在哪、下次遇到同类题怎么快速切入。适合谁看两类人。一类是正在准备校招的应届生尤其是Java方向的同学这套题的考点覆盖面非常典型做透它能帮你省掉大量盲刷时间另一类是准备跳槽的初中级工程师用来做知识体检也很划算——很多平时写业务代码根本碰不到的细节这套卷子里能一次性暴露出来。先给一个总体判断这份卷子的难度曲线是“中段陡峭、首尾平缓”。前面的Java基础选择题大部分送分中间集合、并发、JVM的部分开始分人最后手写代码题真正拉开差距。接下来我们按这个顺序逐步拆解。1.1 网易笔试题型的三个稳定板块网易这类互联网大厂的校招笔试Java卷基本都遵循同一个结构模板18年也不例外板块常见题型核心考察目标大致占比Java基础与面向对象单选题、多选题语法细节、内存语义、设计原则30%集合框架、并发、JVM单选题、多选题、判断题底层原理、边界行为、异常场景40%编程题在线编码数据结构、算法思维、代码规范30%这里面有一个容易被忽略的事实选择题的考察方式往往比编程题更“毒”。编程题至少给了你完整的上下文选择题经常只给一小段看似人畜无害的代码然后问你输出什么。这类题几乎没有“蒙对”的可能要么你对底层机制真的理解到位要么就只能错。我当年刷这套题时最深的感受是选择题部分对“正确但不够深入”的复习方式极其不友好。你懂得“HashMap大致是数组加链表”和你能确切说出JDK 8在什么条件下把链表转成红黑树做题的准确率完全不同。1.2 高频考点六年前后几乎没变的底层逻辑为什么Java校招笔试的考点这么稳定原因并不复杂。校招本身就是一场“能力下限测试”公司不指望应届生上来就能写高并发中间件但必须确保你具备扎实的计算机基本功、严谨的编程习惯、快速学习的能力。而Java这套技术栈里最符合这些考察目标的恰恰是那些最底层的知识JVM如何管理内存、集合在多线程环境下为何不安全、类加载如何保证核心库安全……这些知识十年不变自然年年考。另一个原因是面试流程的“接力效应”。笔试的考点往往就是随后的技术面最可能追问的方向。你在笔试卷里看到的HashMap扩容问题几乎一定会演变成一二面时“你来设计一个线程安全的HashMap”的开放式追问。所以把笔试卷当成面试的预演提纲比单纯背答案有价值得多。2. Java基础选择题那些看似简单实则送命的陷阱网易这张卷子的Java基础部分命题人明显在“认真读题”和“对语言的精确理解”上做文章。很多题单看知识点你觉得自己会实际做起来却会踩坑。下面几类是出现频率最高、错误率也最高的。2.1 String、常量池与“”的判断逻辑这几乎是大厂笔试的固定开场题网易也不例外。给你一段代码问输出什么String s1 abc; String s2 new String(abc); String s3 a bc; String s4 a; String s5 s4 bc; System.out.println(s1 s2); // false System.out.println(s1 s3); // true System.out.println(s1 s5); // false System.out.println(s1.equals(s2)); // true这道题背后的机制很简单但特别容易记混。s1直接赋值会把字符串放进常量池s2通过new创建一定在堆上产生新对象即使常量池里已经有相同内容的字符串两者也不是同一个引用。s3是编译期常量折叠a bc在编译阶段就合并成了abc所以直接指向常量池里的同一个对象。而s5涉及变量s4编译器无法在编译期确定值只能在运行期用StringBuilder拼接结果是新对象。这里要补一个容易忽略的细节String的intern()方法。如果把s2.intern()的返回值赋给新变量它会返回常量池中的引用。笔试偶尔会把这个方法混进选项里考察记住它的语义就够了常量池中已存在相同内容的字符串时直接返回池中引用否则把当前字符串加入池中并返回引用。2.2 Integer缓存、自动装箱与equals的边界第二类高频陷阱题长这样Integer a 127; Integer b 127; Integer c 128; Integer d 128; System.out.println(a b); // true System.out.println(c d); // false很多人第一次做这道题都会懵都是自动装箱为什么127相等、128不相等因为Integer类内部维护了一个IntegerCache默认缓存-128到127之间的所有Integer对象。在这个范围内自动装箱拿到的都是缓存里的同一个对象超出范围valueOf()会执行new Integer()自然每次都是新对象。注意这个缓存范围可以通过JVM参数调整但校招笔试通常不考这个冷门点。更常见的变体是Integer e new Integer(127); Integer f new Integer(127); System.out.println(e f); // false System.out.println(e.equals(f)); // truenew出来的对象不参与缓存所以即使值相同也一定是false。对比凡是涉及“包装类型比较是否相等”的题统一用equals()判断才稳妥。同类缓存机制在Long上同样存在Short、Byte则因为取值范围天然小缓存覆盖了整个范围笔试如果出这些变体思路完全一致。2.3 继承初始化顺序从静态块到构造器的完整链路网易对面向对象的考察中类初始化顺序是每年必到的考点。题目一般给你几个类包含静态代码块、实例代码块和构造器让你判断创建对象时输出顺序class Parent { static { System.out.print(P-static ); } { System.out.print(P-instance ); } Parent() { System.out.print(P-ctor ); } } class Child extends Parent { static { System.out.print(C-static ); } { System.out.print(C-instance ); } Child() { System.out.print(C-ctor ); } } new Child(); // 输出P-static C-static P-instance P-ctor C-instance C-ctor记忆口诀就一句话**先静态再父类再子类同类内部先实例块后构造器。**为什么是这个顺序静态代码块在类加载阶段执行所以严格早于任何对象创建创建子类对象时JVM需要先完成父类的实例初始化——因为子类构造器的第一行会隐式调用super()而super()执行前必须先执行父类的实例代码块。这个机制是由JVM规范从底层强制保证的不是某个IDE的约定。有个很阴险的变体把new Child()换成Child c null;问静态块是否执行。答案是不执行类加载发生在真正需要创建对象或访问静态成员时仅仅声明一个引用变量不会触发任何加载动作。2.4 面向对象设计题的判断标准除了语法题网易基础部分还会穿插几道设计原则相关的选择题考得比较多的有单一职责原则、开闭原则、里氏替换原则的应用判断。比如给你一个类图或一段代码问“修改某个类增加新的输出格式违反了哪条设计原则”。看到“增加新功能需要改动已有类的内部代码”基本可以锁定是违反开闭原则——开闭原则要求对扩展开放、对修改关闭正确做法是新增子类或实现类而不是改动原有的、已验证逻辑的类。这类题的做题技巧和语法题完全不同语法题考的是“机制记没记住”设计题考的是“原则能不能对应到具体场景”。建议把六个常用原则单一职责、开闭、里氏替换、依赖倒置、接口隔离、迪米特法则各准备一个正反案例笔试时直接匹配场景。时间紧张的话优先准备开闭和单一职责这两个出现率最高。3. 集合框架与并发笔试中最容易拉开差距的考点群如果把Java基础部分比作“热身”集合与并发就是“上强度”。网易这套卷子在这一块出题非常密集而且特别喜欢把“集合在多线程环境下的表现”和“并发工具的实现原理”放在一起考。这也是校招笔试中区分度最大的知识点群。3.1 HashMap的底层演进与put流程HashMap相关题目在笔试中的统治地位几乎可以单独写一篇长文。网易18年卷子中选择题直接考了JDK 8下HashMap的put流程、扩容时机和红黑树化条件。这几个点放到今天依旧高频。JDK 8的put完整流程可以概括为对key做hash扰动高16位异或低16位降低哈希冲突概率判断table数组是否为空空则触发resize()初始化默认容量16根据(n - 1) hash定位桶下标该位置为空直接放进去如果不为空判断头节点key是否和当前key相等用equals判断相等则覆盖如果头节点是TreeNode走红黑树的插入逻辑如果是普通链表节点则尾插法追加到链表尾部追加后如果链表长度达到8且数组长度不小于64链表转红黑树插入完成后如果size threshold当前容量乘以负载因子0.75触发扩容容量翻倍。这里有三个笔试高频考点需要特别记忆。第一为什么容量要求是2的幂因为哈希定位用的是(n - 1) hash位运算等价于对n取模但效率更高前提是n必须是2的幂这样才能保证n - 1低位全为1让哈希值的高低位都能参与定位。第二为什么树化阈值是8这是泊松分布的一个工程权衡结果在随机哈希的理想情况下链表长度达到8的概率极低用红黑树主要是为了抵御极端哈希冲突。第三JDK 7和JDK 8的扩容机制不同JDK 7使用头插法多线程扩容时可能形成环形链表导致get死循环JDK 8改为尾插法解决了这个问题但HashMap本身依然不是线程安全的并发写仍然可能丢数据。3.2 ConcurrentHashMap从分段锁到CAS既然HashMap不是线程安全的笔试紧接着就会考ConcurrentHashMap。网易的题目很喜欢把JDK 7和JDK 8的实现放一起对比问你“哪个说法是错误的”。两张表的答题要点其实浓缩成一句话JDK 7的ConcurrentHashMap使用分段锁SegmentJDK 8抛弃了分段锁改用CAS synchronized锁住单个桶的头节点。为什么JDK 8要改成这种方案分段锁的锁粒度是“一段区域”同一段内的不同桶写入仍然相互阻塞而CAS加锁单个桶节点锁粒度细化到“单个桶”并发度远高于分段锁。同时JDK 8的代码结构也简化了不再需要维护Segment数组直接用Node数组加volatile修饰的next指针就够了。另一个高频笔试点是size()方法。JDK 8的ConcurrentHashMap.size()返回的是近似值先不加锁地统计baseCount和CounterCell数组必要时重试如果竞争仍存在就加锁统计。所以如果你看到选项说“size()方法返回精确值”直接排除。3.3 线程池核心参数与拒绝策略的组合逻辑网易这张卷子的并发部分线程池几乎是必考项重点考两类题一类是七参数据问“缺一个行不行”另一类是给定参数让你算第几个任务会被拒绝。先记住线程池的7个核心参数参数作用笔试题常考陷阱corePoolSize核心线程数核心线程默认不回收maximumPoolSize最大线程数必须大于等于corePoolSizekeepAliveTime非核心线程空闲存活时间只作用于超出核心数的线程unit时间单位配合keepAliveTimeworkQueue任务队列决定了线程池的排队策略threadFactory线程工厂自定义线程名方便排查handler拒绝策略队列满且线程数达到最大值时触发线程池处理新任务的顺序是死的**先看核心线程是否满了没满直接创建核心线程执行满了丢进工作队列队列也满了再创建非核心线程线程数达到最大值且队列也为空时触发拒绝策略。**很多人的误解在于跳过队列直接创建线程实际上核心线程满了之后新任务先进队列而不是立刻增加线程。生产环境中这也是一个常见的性能误判点你配了核心10线程、最大50线程但队列是无界的结果永远只有10个线程在跑堆了一堆任务在队列里排队。四种拒绝策略需要能区分AbortPolicy直接抛异常默认策略CallerRunsPolicy让提交任务的线程自己执行该任务DiscardPolicy静默丢弃DiscardOldestPolicy丢弃队列中最早的任务。网易喜欢把CallerRunsPolicy单独拎出来考因为它有“背压”效果能减缓任务提交速度面试时也容易深入聊。3.4 synchronized、ReentrantLock与volatile的分工并发章节最后一块拼图是锁机制和内存可见性。这部分的题目多数是概念辨析但概念辨析恰好是最容易出错的。synchronized和ReentrantLock的核心区别前者是JVM层面的关键字后者是JDK提供的API前者自动释放锁后者需要手动在finally中释放前者不可中断、非公平后者支持可中断、可限时、可选公平/非公平前者通过对象监视器实现底层依赖monitorenter/monitorexit指令后者基于AQS实现。volatile则是另一套机制它保证两个特性可见性和有序性但不保证原子性。最经典的笔试陷阱就是ivolatile int count 0; // 多线程执行 count结果一定小于等于线程总数因为count在字节码层面是“读取、加一、写回”三步volatile只能保证写回结果对其他线程可见却无法阻止多个线程同时读到旧值。解决这个问题要么用AtomicInteger要么加锁。还有一个高频点是双重检查锁单例DCL。这段代码中instance字段必须用volatile修饰原因是new Singleton()不是原子操作在JVM层面分为“分配内存、初始化对象、设置引用指向”三步编译器和CPU可能重排序。如果不加volatile另一个线程可能在线程A刚完成第二步时就看到非空的引用拿到的却是尚未初始化完成的对象。4. JVM、类加载与内存管理网易的高区分度考点JVM章节在网易这套卷子里属于“送分题和送命题并存”的板块。简单题考你Java内存分哪几块难一点的直接给一段配置参数考你OOM类型。如果你只是想应付笔试主攻“双亲委派”和“OOM类型”两个方向性价比最高。4.1 双亲委派模型为什么核心类不能被随便替换类加载部分的高频选择题几乎都围绕双亲委派模型展开。JVM默认有三个层级的类加载器启动类加载器Bootstrap负责加载rt.jar等核心库、扩展类加载器ExtensionJava 9以后改称平台类加载器Platform、应用类加载器Application加载classpath下的类。双亲委派的核心逻辑是当一个类加载器收到类加载请求它不会自己先去加载而是先把请求委派给父加载器父加载器处理不了子加载器才尝试自己加载。为什么要设计成这样原因有二。第一避免类被重复加载——同一个类如果被不同加载器加载JVM会认为是两个不同的类容易引发类型不匹配异常第二保证核心API安全——比如你写了一个java.lang.String如果不走双亲委派应用类加载器就可能自己加载这个伪造的String破坏整个Java运行时的基础。由于双亲委派机制的存在加载java.lang.String的请求最终会被顶到Bootstrap加载器它发现rt.jar里已经有String了就不会去加载你写的那个类。这里有个延伸考点SPI机制为什么要用线程上下文类加载器来打破双亲委派因为双亲委派是“父加载器优先”而JDBC这类SPI场景中DriverManager由Bootstrap加载器加载但它需要调用由应用类加载器加载的数据库驱动按照双亲委派模型根本无法加载。线程上下文类加载器允许父级加载器反过来使用子级加载器去加载类算是双亲委派的一个例外。笔试如果考到“哪种机制打破了双亲委派”选线程上下文类加载器。4.2 JVM内存区域与OOM类型的对应关系内存区域的题几乎年年见而且网易喜欢用“这段代码运行后哪个区域会抛出OutOfMemoryError”的形式来考。先把内存分区理清楚区域线程私有/共享是否可能OOM常见触发场景程序计数器线程私有不会无Java虚拟机栈线程私有会无限递归导致栈深度超限本地方法栈线程私有会本地方法栈溢出Java堆线程共享会对象过多且无法回收方法区/元空间线程共享会动态生成大量类其中最容易混淆的是栈溢出StackOverflowError和堆溢出OutOfMemoryError: Java heap space的关系。无限递归方法调用会不断压栈最终栈帧超出虚拟机栈容量抛的是StackOverflowError而不是OutOfMemoryError——前者属于错误栈溢出后者属于内存空间不足。题目如果给你一个递归代码问会抛出什么异常记住这两个不能混。关于OOM类型笔试常考的有四种java.lang.OutOfMemoryError: Java heap space堆内存不足最常见的OOM大量对象强引用未释放java.lang.OutOfMemoryError: Metaspace元空间不足常见于动态生成大量代理类或字节码增强框架使用不当java.lang.OutOfMemoryError: unable to create new native thread无法创建新的系统线程常见于线程数爆了而内存还有富余java.lang.OutOfMemoryError: GC overhead limit exceededGC频繁回收但回收效果极差JVM保护机制触发。看到unable to create new native thread时很多人第一反应是加堆内存这恰恰是南辕北辙。这种OOM通常是栈内存占用了进程地址空间或操作系统线程数受限导致的应该减少线程数量或调小单个线程栈大小而不是增大堆。4.3 GC判定与垃圾回收器选择垃圾回收相关的题网易更偏向测“概念理解的准确性”而不是让你背诵某款收集器的全部参数。先记住一个核心点**JVM判断对象是否存活的算法是可达性分析而不是引用计数。**引用计数无法解决循环引用问题——两个对象互相引用但外部已经没有引用指向它们计数永远不为零就永远无法被回收。可达性分析从GC Roots集合出发向下遍历凡是无法达到的对象即标记为可回收。常考的可作为GC Roots的对象包括虚拟机栈中引用的对象、静态属性引用的对象、常量引用的对象、本地方法栈中JNI引用的对象。垃圾回收算法的选择题一般考三种算法的适用场景。标记-清除是基础优点是实现简单缺点是产生内存碎片标记-复制适合新生代因为新生代对象大多朝生夕灭复制成本低缺点是浪费一半空间所以HotSpot的Eden和Survivor按8:1分配标记-整理适合老年代能解决碎片问题代价是移动对象的开销大。垃圾回收器方面校招笔试不需要你把所有收集器参数背到滚瓜烂熟但需要知道CMS和G1的核心区别。CMS以“最短停顿时间”为目标采用标记-清除算法会产生碎片G1把堆划分为多个Region可以指定最大停顿时间整体上更适合大堆和需要可预测停顿的场景。网易如果出“在停顿时间敏感的大内存应用中最适合选择哪个垃圾回收器”的选择题答案是G1。4.4 常见OOM场景的排查思路虽然笔试大多只考到“判断OOM类型”但网易偶尔会出一道场景题给你一段代码和报错信息让你选排查手段。这类题我在实际工作里帮人排查过很多次完整思路其实就三步。第一步从异常信息判断堆还是非堆。报错包含Java heap space基本确定是堆不够包含Metaspace则是元空间问题。工程中为了快速定位一般会在JVM参数里加上-XX:HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath/path/to/dump让JVM在抛出OOM前自动导出堆快照。第二步用jmap或jstat看当前堆占用和GC情况。jmap可以查看堆摘要、类加载情况jstat可以观察S0C、S1C、Eden、Old等区域的使用率以及频繁的GC次数。如果Full GC非常频繁而内存回收量极少同时伴随GC overhead limit exceeded说明存活对象极多且难以回收大概率存在大对象集合被长生命周期对象持有。第三步分析堆转储文件。用Eclipse MAT或JProfiler打开dump文件直接看“Dominator Tree”或“Leak Suspects”找占用内存最大的对象及其引用链。绝大多数内存泄漏都能在这个步骤里定位到具体代码位置。笔试选择题常见的正确选项就是在这些工具里选一个。5. 手写代码题从快速排序到链表的套路化训练网易这套卷子的编程题难度设定比较务实一般两到三道涵盖了排序、链表、动态规划这类经典题型。不会刻意出偏题怪题但非常在意代码质量和边界条件的完整性。很多同学算法思路没问题却挂在边界判断和输入输出处理上非常可惜。5.1 排序算法的手写标准与边界检查“手写快速排序”几乎是Java校招笔试的保留节目。网易编程题也出现过而且网易的判题系统会对边界数据做严格测试空数组、全部相等元素、已排序数组任何一类不过都会被标记错误。快速排序的最小可运行写法public void quickSort(int[] arr, int left, int right) { if (left right) return; int pivot arr[left]; int i left, j right; while (i j) { while (i j arr[j] pivot) j--; arr[i] arr[j]; while (i j arr[i] pivot) i; arr[j] arr[i]; } arr[i] pivot; quickSort(arr, left, i - 1); quickSort(arr, i 1, right); }这段代码里最容易写错两处。一是内层循环的比较条件arr[j] pivot和arr[i] pivot必须是和否则遇到和基准值相等的元素时会陷入死循环。二是递归终止条件必须是left right只写left right在空数组子区间场景下会出错。实际上很多在线判题系统都会塞一个长度为0的边界用例quickSort(arr, 0, arr.length - 1)配合left right才不会崩。如果你的编程题时间紧张排序算法只需要重点准备快速排序和归并排序其他排序在笔试中考察率极低。归并排序用于链表排序场景和数组排序并列准备即可。5.2 链表类题目的万能模板链表题在网易编程题里出现过多次核心原因很简单链表是考察指针操作和递归思想的最短路径。链表题虽然变化多但解法高度模板化。链表反转是几乎所有链表题的“公因式”。public ListNode reverseList(ListNode head) { ListNode prev null; ListNode cur head; while (cur ! null) { ListNode next cur.next; cur.next prev; prev cur; cur next; } return prev; }注意这里的next节点必须在修改cur.next之前保存因为一旦把当前节点的指针指向前驱原来的后继节点就“丢了”。很多新手第一次写链表反转就错在这一行——总想先改cur.next再找next结果链表断成两截。另一个高频模板是快慢指针找中点ListNode slow head, fast head; while (fast ! null fast.next ! null) { slow slow.next; fast fast.next.next; } // slow 即中点这个模板配合“判断链表是否有环”时循环条件还得加一个fast.next.next ! null的保护判断避免空指针异常。笔试判题时空指针是扣分最多的错误类型写循环条件之前先想清楚fast和fast.next可能为空的场景。还有一个加dummy哨兵节点的技巧当需要删除头节点或者操作可能涉及头节点变更时先创建一个虚拟头节点指向head操作结束后返回dummy.next。这能省掉大量“头节点特判”的代码也不容易漏边界。5.3 动态规划题目的识别与基础模型网易编程题在算法层面偏爱动态规划。原因不难理解DP既能考察基础状态定义、状态转移方程又能通过题目包装区分“刷过题”和“真正理解”的候选人。笔试现场如何快速识别一道DP题核心看两点问题是否具有最优子结构子问题的最优解可以推导出原问题的最优解是否有重叠子问题递归求解过程中同一子状态被反复计算。具备这两点基本就是DP的靶子。典型的反例是“求全排列”它属于回溯不适合DP。最常考的DP模型有四个一维线性DP比如爬楼梯、打家劫舍。状态定义为dp[i]表示走到第i步的最大收益转移方程通常只依赖前一个或前两个状态二维网格DP比如从左上角到右下角的最小路径和。状态定义为dp[i][j]表示到坐标(i,j)的最优值转移方向为从上到下、从左到右背包问题0-1背包的状态定义是dp[i][j]表示前i个物品装入容量为j的背包的最大价值转移方程是dp[i][j] max(dp[i-1][j], dp[i-1][j-w[i]] v[i])笔试常考01背包的滚动数组优化写法最长递增子序列LISdp[i]表示以第i个元素结尾的最长递增子序列长度二重循环求解时间复杂度O(n²)。进阶技巧是贪心加二分但笔试用O(n²)版本通常已经能拿到不错的分数。网易笔试DP题的一个特点是题目描述会故意披上复杂的故事外衣。实际解法还是那几个基础模型。如果放在笔试卷的编程题里建议先花30秒把题目里的“故事”剥离干净只保留数字、约束和决策条件然后再对照模型套状态定义。5.4 笔试环境下的输入输出与调试技巧编程题丢分的另一个重灾区是输入输出处理。网易的在线笔试系统Java纯文本的输入通常需要我们通过标准输入逐行读取。Scanner当然能用但在数据量大的场景下性能很差。推荐这种写法BufferedReader reader new BufferedReader(new InputStreamReader(System.in)); String line; while ((line reader.readLine()) ! null) { String[] parts line.trim().split( ); }两个注意事项。第一题目要求输入多行格式不固定时一定要用循环读取而不能只读一行这是在线笔试最常见的崩溃原因。第二不要在输出时夹杂调试信息比如System.out.println(result is ans)——在线判题系统直接比对标准输出和期望输出多打一个字都算错。调试技巧方面本地IDE写完后先在答题框里复制一个最小用例跑通再看边界用例。时间分配上我的经验是三道编程题第一道15分钟内必须做完如果卡题超过20分钟果断换下一道回头再啃。笔试真正拼的往往是“会做的题能不能全做对”而不是“不会的题能不能硬啃下来”。6. 刷完这套卷子后我更建议你做这三件事很多同学刷笔试卷的习惯是“对完答案就翻篇”分数看着还行下次遇到同类题照样错。我刷网易这套题时踩过不少坑复盘下来最有价值的不是题目本身而是刷题方法。分享三个我后来一直沿用的习惯。6.1 用限时模拟代替无约束刷题校招笔试的时间压力是真实存在的。网易这套卷子的选择题和编程题加起来考试时间通常只有90到120分钟平均到每道题上时间并不宽裕。第一次刷建议严格按照考试时间来打开计时器中间不能查资料、不能切出去看知识点模拟真实环境的紧张感。刷完后记录分数同时记录“哪类题超时最多”。我自己的统计中集合与并发部分的选择题是超时重灾区主要原因是选项里有多个似是而非的说法需要逐一排除。超时最多的部分就是你基础最薄弱的部分后续复习资源优先倾斜到那里。6.2 错题按“考点”归档而不是按“题型”归档按题型归档容易让人陷入“背题”的误区。比如你记录“我错了一道关于HashMap的题”这道题的知识点可能同时涵盖哈希函数设计、扩容机制、树化条件甚至线程安全。下次面试官换个角度问HashMap你就未必答得出来。推荐按考点归档建立一份自己的错题表格每个考点一列记录出错原因和正确的理解方式。比如考点错误理解正确理解HashMap容量为什么是2的幂为了均匀分布为了用位运算替代取模volatile能否保证原子性能只保证可见性和有序性不保证原子性双亲委派的意义加快加载速度避免重复加载、保护核心类我自己在准备校招时这份表最后积累了几十个考点考前过一遍比盲目刷一百道新题有用得多。因为错题表格记录的才是真正的盲区新题做的再多如果不知道自己哪里不懂只是在加强已经掌握的知识。6.3 把笔试考点扩散成面试问答串最后是一个利用笔试卷的最高级玩法把笔试中的每个核心考点都准备成一道面试追问链。网易笔试考的HashMap树化阈值是8那么面试官接下来很可能问“为什么是8”“如果阈值是1会怎样”“红黑树和链表哪个更耗内存”。笔试考的volatile面试可能会延伸成“讲一下JMM内存屏障”或“双重检查锁为什么不能去掉volatile”。笔试其实是给你划好了面试复习范围网上流传的各种“面试八股文”其最底层骨架就藏在这样一份笔试卷里。我的建议是每做完一套卷子挑5个错得最多的考点针对每个考点写一段200字以内的“面试答法”——先说结论再讲机制最后举一个实际场景。写完后对着镜子或录音里念一遍如果发现自己说不顺就是理解还不到位。这个方法我用过很多次基本可以覆盖技术面试60%到70%的问法。剩下的就是多面几轮积累临场状态了。如果你手头的笔试卷数量有限网易这套2018年的题可以当作第一套全真模拟来用。做完之后把本文提到的几个高频考点逐一过一遍再去找两三套近年的大厂笔试卷交叉验证很快就能建立起一套属于自己的Java校招备考框架。框架一旦建立后面再刷题就不再是“看一道会一道”而是“新题进来、归位到框架里”了。