
离网易2020校招提前批Java开发工程师笔试过去一段时间了但那次笔试给我的印象还挺深的。当时我在牛客网上刷完一堆真题又在网上翻各种面经结果真正坐到电脑前打开笔试页面的时候还是被几道题闪了一下腰。印象最深的倒不是题有多难而是题目的出题思路——它不考你背多少八股文而是看你能不能把Java的基础概念、为什么这么设计讲清楚并且用代码验证出来。这次笔试总共两个小时左右题型大概是单选、多选、简答加编程题其中编程题占了大头。网易笔试的编程题不是让你写完整工程而是给你一个核心方法你用Java实现出来输入输出走标准IO。这种模式对代码功底要求很直接边界条件、内存占用、运行时长都会成为隐形评分点。如果你正在准备各大厂的Java校招笔试或者想趁着秋招提前批试水这篇复盘应该能帮你少走不少弯路。我会把这次笔试的考点分布、典型题目、踩坑细节和准备路线完整拆开来讲哪怕题目本身时效性过去了背后的考察逻辑和复习方法依然可复用。1. 笔试整体设计与考点分布1.1 提前批笔试和正式批有什么不同先说一个很多人会忽略的背景信息校招提前批笔试和正式批笔试的定位不一样。提前批的核心目的是抢人所以笔试更多是筛掉基础明显不过关的候选人而不是完美筛选出最强者。网易提前批的题量、题型更偏向考察快速反应和计算机基本功不会故意出偏怪难题反而更看重你是不是真的理解Java这门语言以及有没有扎实的数据结构和算法底子。从我参加的那场来看整张卷子结构大概如下选择题单选多选覆盖Java基础、集合框架、并发、JVM、数据库、计算机网络。这部分大概占30%到40%的分数每题虽然不大但覆盖面极广错了很可惜。简答题一般会有两三道比如让你解释某种机制的原理或者给一段代码判断输出结果。这里考的是语言表达和底层理解死记硬背的人很容易翻车。编程题通常是两到三道考察算法和代码实现。网易挺喜欢考数组操作、链表、二叉树、排序、动态规划这些经典题型。代码量不大但边界条件很刁钻。提前批的笔试时间一般比正式批短一些有些场次甚至只有90分钟。这就意味着你几乎没有时间反复打磨代码必须一次写对。平时刷题就要养成先想清楚再动手的习惯别指望考场上有时间用IDE反复调试。1.2 网易笔试到底想筛什么样的人很多人误以为大厂笔试就是刷题库只要LeetCode刷够500题就能稳过。但网易这类公司的笔试出题逻辑不太一样——他们更想筛出基础扎实、思路清晰、能干活的人。从考点分布来看Java基础占了很大的比重。比如String、equals和hashCode、HashMap底层、异常处理、泛型擦除、反射这些题目几乎每场笔试都会出现。Spring、MyBatis这类框架反而考得少因为校招生还没进公司框架可以后面再教但语言基础和算法思维不是短期能补的。再说算法题网易不追求那种需要奇技淫巧的困难题反而很看重基本功比如链表反转、快排、二分查找、层序遍历。如果你能把这些题写得没有一丝破绽分数基本就很稳了。还有一点值得注意网易笔试的选择题里经常混入一些看代码说结果的题比如并发环境下变量自增的输出顺序、finally和return的执行顺序、字符串拼接的结果。这类题不背口诀而是考你对Java虚拟机执行细节和语言规范的理解。平时写代码别看结果对就完事要多问一层为什么是这个结果。2. 核心考点拆解Java基础与集合框架2.1 String、字符串常量池与经典笔试题String绝对是Java笔试的钉子户几乎每一场都会遇到。网易的题目也不例外。核心考点基本围绕不可变性、常量池、StringBuilder和StringBuffer的区别以及intern方法。先看一个经典题String s new String(abc) 创建了几个对象很多人脱口而出两个一个是abc在常量池中的对象另一个是new在堆中的对象。严格来说如果常量池中已经有abc就只创建了一个堆对象如果没有则会先在常量池中创建abc再在堆中创建String对象也就是两个。这个如果已经有了的前提很多人会漏答。还有一道常见变形题String a abc; String b new String(abc); System.out.println(a b); // false System.out.println(a.equals(b)); // true System.out.println(a b.intern()); // true这里要理解比较的是引用地址equals比较的是内容值intern会把字符串放到常量池并返回常量池引用。笔试如果出这道题考察点就是这三个概念的组合。另一个高频考点是StringBuilder与StringBuffer的区别StringBuffer的方法加了synchronized所以线程安全但性能稍差StringBuilder线程不安全但性能更高。在单线程环境下编译器拼接字符串时默认使用的是StringBuilder比如a b反编译后就是new StringBuilder().append(a).append(b)。不过循环里频繁拼接还是建议自己写StringBuilder因为每次循环都会创建新的StringBuilder对象性能依然有损耗。2.2 HashMap底层原理为什么容量是2的幂集合框架里HashMap是必考中的必考网易笔试几乎每场都有。从JDK 7到JDK 8HashMap的底层变了不少但核心考点相对固定数组加链表JDK 8及以后加上红黑树、put流程、扩容机制、为什么容量是2的幂。先看put流程对key的hashCode做扰动计算也就是高16位异或低16位目的是让哈希值的高位也参与数组下标计算降低碰撞概率。根据哈希值和数组长度计算桶下标公式是 (n - 1) hash而不是 hash % n。因为n是2的幂所以 (n - 1) hash 等价于 hash % n但位运算更快。如果桶位为空直接放如果不为空判断key是否相同相同则覆盖不同则尾插法JDK 8加入链表或红黑树。链表长度超过8且数组长度不小于64时链表转红黑树。扩容时容量翻倍元素重新计算位置。面试官和笔试题都喜欢追问为什么容量必须是2的幂因为只有容量是2的幂n - 1的二进制位全是1这样 (n - 1) hash 才能均匀散列。如果容量不是2的幂位运算会丢失哈希值的一些信息碰撞概率大幅上升同时扩容后的元素分布也会非常不均匀。这是HashMap设计上的一个精妙之处笔试答出这一点会加分。还有一个常考细节JDK 7的头插法和JDK 8的尾插法。头插法在并发扩容时会产生循环链表导致CPU 100%、死循环所以JDK 8改成尾插法从机制上规避了这个问题。但要注意改成尾插法不代表HashMap是线程安全的并发写入依然可能丢数据正确做法是用ConcurrentHashMap。2.3 equals和hashCode的约定这个考点不仅是笔试选择题的常客也是面试连环问的切入点。网易的简答题几乎每年都喜欢出为什么重写equals必须重写hashCode。原因其实一句话就能说清因为HashMap、HashSet这类集合依赖于hashCode先定位存储桶再用equals确认相等性。如果两个对象equals相等但hashCode不同它们在HashMap中会被放到不同桶里导致你用equals相同的key去get时根本找不到那个value违反了Map接口的语义。笔试偶尔还会升级一下让你判断下面这种代码的输出class Person { private String name; // 重写了equals但没有重写hashCode } MapPerson, String map new HashMap(); map.put(new Person(张三), value1); map.get(new Person(张三)); // 返回null因为两个Person对象equals相同但hashCode不同Object默认的实现是地址值所以get时算出不同桶位自然取不到值。关于equals与hashCode很多人以为只是背一个必须重写的结论就够了。但笔试如果要拉开区分度会让你判断equals相等时hashCode是否必须相等以及hashCode相等时equals是否必须相等。前者是必须后者不是。两个不同对象的hashCode可能碰撞所以hashCode相等不能推导equals相等。反过来equals相等则必须有相同的hashCode否则HashMap就无法正常工作。这个点建议记为两条硬约束写代码时也要遵循。3. 并发与JVM笔试喜欢挖的深水区3.1 synchronized锁升级与volatile弱保证并发是Java笔试的深水区也是区分背过八股文和真正理解并发的分水岭。网易笔试中synchronized和volatile基本必考一个考察角度通常结合代码输出题比如public class Test { private static volatile int count 0; public static void main(String[] args) throws InterruptedException { for (int i 0; i 10; i) { new Thread(() - { for (int j 0; j 10000; j) { count; } }).start(); } Thread.sleep(3000); System.out.println(count); } }输出是100000吗不是。因为volatile只保证可见性和禁止指令重排序并不保证原子性。count其实是读取、加一、写回三步操作volatile无法让这三步变成一个不可分割的整体。要想得到正确结果得用AtomicInteger、synchronized或者LongAdder。笔试喜欢拿这个题测你对volatile限制的理解。synchronized方面笔试考察的一般是锁升级过程无锁 - 偏向锁 - 轻量级锁 - 重量级锁。JDK 6之后对synchronized做了大量优化锁不是一开始就重而是随着竞争加剧逐步升级。偏向锁会自动偏向第一个获取锁的线程减少无竞争情况下的加锁开销出现竞争后升级为轻量级锁用自旋等待而不是立刻阻塞自旋超过阈值或线程数过多时膨胀为重量级锁进入操作系统内核态阻塞。笔试可能问轻量级锁的适应自旋是什么答案是JVM会根据上次自旋等待的时间动态调整自旋次数。这个点不用背太深但至少要知道自旋是拿CPU时间换上下文切换开销适合锁持有时间短的场景。3.2 线程池的参数设计七参数不是白背的线程池是Java笔试的另一道常考题网易喜欢让考生解释ThreadPoolExecutor构造方法里那七个参数的含义然后让他们回答核心线程数怎么设置。七个参数分别是corePoolSize核心线程数maximumPoolSize最大线程数keepAliveTime非核心线程空闲存活时间unit时间单位workQueue任务队列threadFactory线程工厂handler拒绝策略笔试常给一段代码问当线程池已满、队列已满时新任务会去哪里。答案是触发拒绝策略默认策略是AbortPolicy直接抛RejectedExecutionException。其他策略还有CallerRunsPolicy调用者线程执行该任务、DiscardPolicy丢弃任务但不抛异常、DiscardOldestPolicy丢弃队列中最旧的任务。关于核心线程数设置网上流传很多说法但笔试不需要你给出一个精确的玄学数字而是要看有没有考虑任务特性CPU密集型任务核心线程数建议设为CPU核数加一让每个线程都尽可能跑满CPUIO密集型任务因为线程会经常阻塞等待IO建议设为核心数乘以2甚至更高。如果任务对实时性要求高队列可以考虑有界队列加CallerRunsPolicy避免无界队列导致的内存增长。这里有一个我当年笔试时差点写错的点线程池在核心线程数不满时即使有空闲线程也有任务进来也不会直接创建新线程而是先创建核心线程去处理任务其实不是严格来说是当提交任务时如果运行线程数小于corePoolSize则创建新线程处理任务不管是否已有空闲线程存在。这个细节很容易被忽略建议看到题目时要仔细审题。3.3 JVM内存区域与垃圾回收写Java不能不懂JVM在笔试里通常以选择题和简答的形式出现。网易的题目涵盖两类一类是内存区域划分另一类是垃圾回收与内存溢出排查。内存区域必须分清楚堆、虚拟机栈、本地方法栈、方法区JDK 8后是元空间、程序计数器。笔试爱考哪些区域是线程共享、哪些是线程私有。堆和方法区是线程共享的虚拟机栈、本地方法栈、程序计数器是线程私有的。之后常追问栈溢出和堆溢出分别是什么异常答StackOverflowError和OutOfMemoryError就对了。垃圾回收方面核心是可达性分析算法和GC Roots。从GC Roots出发能到达的对象就是存活对象不能到达的就可以回收。GC Roots包括栈帧中的局部变量、静态变量、本地方法栈引用的对象等。笔试偶尔会问哪些对象可以作为GC Roots这个也是基础建议记住三个以上的例子。内存溢出排查是常考的一个应用型问题。题目一般这样出线上系统频繁Full GC堆内存持续增长怎么排查完整思路是先通过jstat监控JVM GC频率再用jmap导出堆快照由MAT或VisualVM分析大对象和引用链定位到具体的业务代码。网易笔试不要求你在这道题上写太多但能写出jmap MAT分析这个组合说明你确实处理过问题分数会有明显差异。我在准备这块时特意在本地把模拟内存溢出 - 导出堆 - 用MAT分析跑通了一遍笔试遇到类似题目就不会慌。4. 算法题实操:排序、链表与动态规划4.1 排序算法不仅要会写还要知道边界在哪网易笔试编程题考排序的频率非常高尤其是快速排序和冒泡排序。很多人以为排序太基础就不练结果真到笔试时发现越是基础越容易在细节上翻车。以快速排序为例手写核心代码时要注意几点public int[] quickSort(int[] arr, int left, int right) { if (left right) { return arr; } int pivot arr[left]; int i left; int 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); return arr; }边界条件最容易错的地方是内层循环必须判断i j否则会因为越界把数组搞坏。另外如果基准值选最左侧元素就必须先从右侧开始扫描否则最终交换位置会被破坏。这个为什么要先从右往左我当年笔试时没想明白后来复盘才发现是因为最后一个位置要与基准值交换必须保证停下来时指向的是小于等于基准值的元素。排序算法的稳定性和时间复杂度也要一起背清楚冒泡和插入是稳定的快排、选择、堆排不稳定快排平均O(n log n)最坏O(n^2)。笔试偶尔会问稳定排序有哪些答不上来就很亏。冒泡排序在笔试里更常作为入门题出现但有时候会以优化形态出现比如如果某一轮没有发生任何交换说明已有序提前终止。能写出这种优化会给阅卷者留下好印象。4.2 高频算法题:代码风格和套路比奇技淫巧重要网易笔试编程题一般不会出那种需要冷门数据结构的高级题反而很钟爱经典的LeetCode高频题。我从不同场次的反馈中总结了几个高频方向数组两数之和、三数之和、合并两个有序数组、移动零、最大子数组和。链表反转链表、合并两个有序链表、环形链表、删除倒数第N个节点。二叉树前序/中序/后序/层序遍历、二叉树最大深度、最近公共祖先。动态规划爬楼梯、最长递增子序列、打家劫舍、零钱兑换。以两数之和为例笔试最希望看到的是用HashMap把时间复杂度从O(n^2)降到O(n)的解法public int[] twoSum(int[] nums, int target) { MapInteger, Integer map new HashMap(); for (int i 0; i nums.length; i) { int complement target - nums[i]; if (map.containsKey(complement)) { return new int[]{map.get(complement), i}; } map.put(nums[i], i); } return new int[]{-1, -1}; }这段代码看起来简单但要注意必须先判断containsKey再put否则遇到重复元素时可能把自己当成答案。比如数组是[3, 3]target是6如果先把第一个3放进去再判断第二个3时containsKey就会命中从而得到正确结果。所以这个先查再存的顺序不能反。链表题最常考反转链表递归和迭代两种写法都要会。迭代写法比较直观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; }这里最容易写丢的是用临时变量保存cur.next因为一旦执行cur.next prev原来的next就丢了。笔试的IDE一般不会提示这种逻辑错误必须自己靠代码功底兜住。4.3 边界条件与复杂度:笔试里的隐藏分网易的编程题判题时会跑很多极端测试用例。数组为空、长度为1、全是负数、全是相同元素、链表只有一个节点、二叉树只有左子树这些边界必须有意识覆盖。拿最大子数组和LeetCode 53举例经典的动态规划解法是这样的public int maxSubArray(int[] nums) { int cur 0; int max nums[0]; for (int num : nums) { cur Math.max(num, cur num); max Math.max(max, cur); } return max; }很多人会纠结cur num比num小时该怎么办其实答案就是cur舍去之前累计的和从当前位置重新开始。这个思路在笔试中其实想通了就很简单但需要动手验证几个例子才能彻底放心。我建议在纸上画一遍[-2, 1, -3, 4, -1, 2, 1, -5, 4]的执行过程把cur和max每一步都写出来彻底理解DP的状态转移不要只背代码。复杂度的计算也要多留个心眼。笔试偶尔会要求你填写某段代码的时间复杂度和空间复杂度如果没有把握尽量别在代码里使用递归做二叉树层序遍历因为递归的写法容易造成空间复杂度分析困难。层序遍历用队列迭代实现空间复杂度O(n)清晰又不会错。时间复杂度说白了就是看循环嵌套层数和递归深度这个分析能力平时刷题就要养成习惯等到笔试现场再算容易乱。5. 高频题与踩坑实录那些笔试后才懂的事5.1 时间分配:不要死磕一道题网易的笔试编程题通常带部分分不是一定要全过才能通过。选择题和简答题的分数也要保所以时间分配非常关键。我的建议是拿到卷子先花两分钟快速浏览所有题目把会做的、有思路的、完全不会的分别标出来。选择题控制在30到40分钟内完成拿不准的先标记跳过不要在一道题上耗费超过两分钟。简答题和编程题优先做编程题里最有把握的那道因为代码题一旦AC分数就很稳。编程题如果卡了20分钟还没有完整思路果断换下一题。别觉得可惜有些题看着类似LeetCode但实际形态变了不少死磕很容易导致后面的题没时间做。我见过不少同学在第一道编程题上写了快40分钟结果明明后面的题更简单却没时间碰。提前批笔试的题量不大但每一分钟都很值钱。5.2 在线笔试平台与编译环境的坑提前批笔试基本都是在线编程用的平台大概率是牛客网或者网易自己的系统。这类平台有几个共同的坑提前踩过能省很多时间JDK版本不一致。本地用JDK 17平台可能跑JDK 8导致一些新语法报错。比如var关键字、List.of这类API在JDK 8下完全不认识。如果你在代码里用了这些轻则编译失败重则整道题0分。建议平时刷题就用JDK 8或JDK 11别整花活。类名和主方法签名。平台一般要求类名为Main代码从main方法入口执行。如果你从本地复制代码时顺手带上了package语句编译直接挂。考前最好把常用模板存一份省得现场手敲。输入输出格式。笔试平台不搞图形界面所有输入从标准流读取输出打印到标准流。很多人本地测试没问题一上在线平台就疯狂报错多半是没正确处理多行输入或者输出多了一个空格。建议用Scanner或者BufferedReader养成读一行处理一行的习惯。编译错误提示不友好。平台报错经常是编译失败请检查语法但不会告诉你是哪一行。遇到这种情况最稳妥的办法就是把代码在本地IDE里编译一遍逐字逐句检查。我试过因为少写一个分号平台报了一个莫名其妙的错误当时还以为题目理解错了白白浪费了十分钟。顺便说一句本地准备笔试时Java环境变量的配置最好提前弄好。很多人下载了JDK却不会配JAVA_HOME和PATH导致命令行里java -version都跑不起来。这个虽然不算笔试考点但如果你在笔试前临时装环境真的会焦虑到爆炸。Windows下配环境变量就是新增JAVA_HOME指向JDK安装目录PATH里加一条%JAVA_HOME%\bin然后再加一条JAVA_HOME的classpath可选配置实在不行用IDE自带的JDK也行。5.3 八股文怎么背才有用现在网上到处都是Java面试八股文很多人的复习方式就是打开一篇文章从头背到尾但笔试里真正拉开差距的其实不是背得多不多而是能不能灵活运用。我的经验是把八股文按专题串起来理解而不是孤立记忆。比如HashMap线程安全吗这个问题不能只记不安全用ConcurrentHashMap而是要展开HashMap为什么线程不安全JDK 7的循环链表问题JDK 8的尾插法改了什么ConcurrentHashMap在JDK 8里怎么实现锁粒度细化CAS加synchronized锁桶头节点以及putIfAbsent和computeIfAbsent的适用场景。这样连起来记忆笔试无论从哪个角度切入你都能接上话。复习八股文还有一个技巧把答案变成代码验证。比如你背了volatile不能保证原子性那就自己写一个多线程自增程序跑一遍亲眼看输出结果不是预期值。背了HashMap扩容时JDK 7头插法会循环链表就在JDK 8里跑一个并发场景看看数据丢失。这些自己验证过的记忆远比单纯背诵深刻。网易笔试的选择题和简答题考的就是这种经过验证的理解而不是背诵的原文。6. 备赛路线:从提前批到正式批的完整准备6.1 Java学习路线整理别让零散知识坑了自己如果你现在还处于Java语法学了一些但总觉得知识不成体系的阶段建议先停下刷题整理一份学习路线把散落的知识点串成网状结构。我按个人经验整理了一条适合校招笔试的路Java语法基础变量、运算符、流程控制、面向对象、接口、异常、泛型、集合框架。这一步的目标是能独立写出健壮的小程序比如学生管理系统、计算器。JVM与内存先从内存区域和垃圾回收入手再逐步深入到类加载、字节码、调优工具。目标是能解释Java为什么是跨平台的对象创建后放在哪里什么时候触发GC。并发编程线程创建方式、锁、同步工具类、线程池、并发容器。目标是理解并发问题的本质能写出线程安全的代码。Spring与Spring BootIoC容器、AOP原理、事务管理、自动配置。目标是用框架快速实现一个业务系统同时能说清框架背后的机制。项目实践把学到的东西落到一个完整项目上比如一个在线考试系统、二手交易平台、博客系统。项目不必高大全但一定要能讲清楚技术难点和解决方案。这条路线看起来很长但如果每天能保证高效学习四五个小时一到两个月就能搭建完成。网易提前批笔试的消息通常发布较早正式批又有后续补录所以第一场没通过不意味着秋招就结束了后面还有的是机会。6.2 项目和简历技术栈笔试的隐形加分项严格来说笔试只看答题情况但简历上的技术栈会影响你是否被捞起来面试。网易的流程一般是简历筛选 - 笔试 - 面试笔试通过后面试官会重新翻出你的简历看看你到底做过什么。简历上的技术栈不要罗列一堆了解级别的名词相反写三到五个真正用过、能扛住追问的技术就够。比如Spring Boot、MyBatis、MySQL、Redis、消息队列。笔试阶段虽然是机器判分但你在简答题里体现出的工程思维比如用Redis做缓存时如何处理缓存穿透为什么数据库索引选B树都会成为面试官翻阅简历时的印象分。我自己的经验是简历上写项目一定要有量化描述。比如优化了接口查询性能QPS从200提升到1500就比使用缓存优化了接口性能好得多。这种表述不光是给面试官看更是在帮你梳理项目中的技术亮点笔试遇到相关题目时你也会因为真正做过而多一份底气。6.3 笔试后的复盘方法把经验变成分数考完笔试后不要急着对答案更不要因为一两道题没做出来就陷入焦虑。我觉得最有价值的动作是当天就做一次完整复盘把每道题对应的知识点列出来标记出会做但做错了和完全不会两类。对于会做但做错了的题大概率不是因为不懂而是因为审题不仔细、边界条件漏判、代码风格不统一。这些问题在笔试中非常致命因为机器判题只看结果不会给你平时分的同情。我的办法是每道编程题在提交前强制检查三件事数组是否越界、是否处理了空输入、循环里是否有死循环风险。就算这三件事都检查完还会再跑一两个自己构造的极端用例。对于完全不会的题要把它当作查漏补缺的信号。比如你发现动态规划的题完全没思路那说明你在这方面需要专项突破。不要想着笔试已经考完算了而是要回到专题把基础题型刷透。复盘还有一个容易忽略的点把做错的题整理成一个错题本不仅记录正确答案更重要的是记录当时为什么做错。过一周再回头看一遍效果会很明显。我备考时把错题本按Java基础集合并发JVM算法分好类每次刷题前都会扫一眼后来我发现很多错误其实是同一类思维误区比如默认集合都是线程安全的默认数组不会越界默认输入格式很规范。把这些偏见改掉笔试的正确率会稳步上升。网易2020校招提前批Java开发工程师笔试确实有点 含金量它不是那种靠考前冲刺就能轻松拿下的考试更像是一场对Java综合能力的基本面体检。我到现在还记得自己当时在字符串常量池那道选择题上的犹豫也记得第一道编程题因为忘记处理空数组而被扣分的遗憾。这些经历在事后看都是很宝贵的提醒基本功这件事平时不练扎实笔试就一定会暴露。如果你正在准备类似的校招笔试希望这篇复盘能帮你少踩一些我踩过的坑。最后再分享一个小经验离笔试还有三天的时候别刷新题了把做过的错题和常见代码模板过一遍比什么都管用。