网易校招Android笔试题全解析:Java基础与Android核心考点实战

网易校招Android笔试题全解析:Java基础与Android核心考点实战 网易2018校招Android开发工程师笔试卷我当年是真刀真枪做过一遍的。那会儿秋招刚开始手里拿着一堆打印出来的真题晚上在图书馆一遍遍推演白天就跑去机房敲代码练手感。现在回头看这套卷子虽然叫“2018校招”但它覆盖的知识面、考察的深度放到今天依然能打很多大厂Android岗的笔试题都还在用同样的套路出题。这篇文章我就把当年刷这套题的经验、踩过的坑、总结出来的解题思路全部摊开讲不管是正在准备校招的应届生还是想跳槽巩固基础的Android开发都能从里面拿到点实在的东西。先说结论网易这套笔试卷核心就考三块——Java基础与并发、Android四大组件与消息机制、算法与数据结构编码题。附加题偶尔会有网络、操作系统、数据库的内容但占比不大。整张卷子时间特别紧我记得好像是90分钟题量却不少单选多选加两道编程题很多人根本做不完。所以这套卷子考验的不只是你会不会更是你在压力下能不能快速判断、果断取舍。1. 笔试整体认知与题型分布1.1 网易笔试题型结构与时间分配2018年这套卷子的题型大致分四类单选题、多选题、编程题以及个别年份会出现的简答题。单选题大概20到30道覆盖面极广从Java语法细节到Android组件的使用场景都有多选题大概10道左右难度明显上升选项里经常出现“看似对但其实描述不严谨”的干扰项编程题一般是两道一道偏算法一道偏Android场景模拟比如设计一个缓存、实现一个生产者消费者模型。我当年第一次做这套题的时候直接栽在时间分配上。前面选择题花太多时间纠结结果编程题只剩20分钟第二道题只写了个开头就交了。后来我调整了策略拿到卷子先花两分钟扫一遍全卷把编程题大概看一眼心里有数然后选择题单题不超过60秒拿不准的先标记跳过最后回头再看。这样至少能保证两道编程题都有时间动手。1.2 考点权重分布与复习优先级从真题统计来看考点权重大概是这个分布Java基础集合、并发、JVM约占30%Android基础四大组件、Handler、启动模式、布局约占30%算法与数据结构约占20%网络与操作系统约占15%其他设计模式、数据库、Git等约占5%。这意味着复习的优先级其实非常明确Java基础和Android基础是绝对的基本盘这两块只要吃透了选择题的保底分就到手了。算法题决定你能不能进下一轮面试网易的算法题不算特别变态基本在LeetCode中等难度以内但要求你在笔试环境里手写出能跑通的代码这就很考验基本功了。注意多选题是重灾区。Android的多选题经常考察“以下哪些说法正确”四个选项里往往有三个看起来都对。我建议多选题当成判断题来做每个选项逐字抠尤其是“一定”“必须”“所有”这类绝对化表述八成为错。2. Java与Android核心基础高频考点2.1 Java集合与HashMap源码细节网易的笔试卷子特别喜欢考HashMap而且是那种“源码级”的考法。我记得有一道多选问的是HashMap在JDK 1.7和1.8之间有哪些变化选项里包含了“头插法改尾插法”“引入红黑树”“resize时是否重新计算hash”“初始容量和负载因子”等。如果你只停留在会用HashMap.put/get的阶段这种题基本靠蒙。这里我建议认真理解几个核心点。第一HashMap的put流程计算key的hash值通过扰动函数减少碰撞定位到桶的位置如果桶为空直接放如果桶不为空遍历链表或红黑树找相同key有就覆盖没有就插入。第二扩容机制默认初始容量16负载因子0.75当元素个数超过容量乘以负载因子时触发扩容扩容为原来的两倍。JDK 1.7是全部重新rehash1.8做了优化利用元素hash值高位是否变化将链表拆成高低位两条链避免大量重算。第三为什么线程不安全JDK 1.7在多线程同时put并触发扩容时头插法可能导致环形链表get时出现死循环1.8解决了这个问题但多线程下put仍可能覆盖丢失数据。与之配套的还有ConcurrentHashMap。网易对并发容器的考察次数也不少核心考点包括JDK 1.7的Segment分段锁设计、1.8改用CAS加synchronized锁头节点、size()是如何在不锁整个表的情况下估算的1.8用CounterCell和sumCount以及为什么读操作不需要加锁Node的val和next用volatile修饰。这些内容笔试时会以选择题形式出现但面试环节也经常追问提前整理好没有坏处。2.2 JVM内存区域与GC机制Android开发虽然和标准JVM有区别Android用的是ART/Dalvik早期还有独立的堆栈模型但校招笔试对JVM的考察仍然很主流因为这是Java开发者的通用基础。网易2018年的卷子里就有一道关于内存区域的单选涉及堆、虚拟机栈、本地方法栈、方法区和程序计数器各自的职责。复习JVM时不要死记硬背我建议用一个“代码运行时发生了什么”的方式来串联。比如你new了一个对象类信息加载到方法区对象的实例数据分配在堆中方法里的局部变量存到栈帧里如果你在方法里new了一个大对象可能触发Minor GC或Major GC。GC算法方面重点理解可达性分析GC Roots以及强引用、软引用、弱引用、虚引用在Android中的典型应用场景——比如图片缓存用LruCache内部是强引用加LinkedHashMap而系统针对内存紧张时的回收优先级就涉及引用的不同级别。网易比较爱考的一个点“强引用置为null之后GC一定会立刻回收它吗”答案是“不保证要看GC何时触发”。很多人一看到置为null就觉得万事大吉实际上置null只是让对象变成“可回收”状态什么时候回收由GC决定。Android里用WeakReference加ReferenceQueue做内存泄漏检测也是利用了GC后弱引用会被放入队列的特性。2.3 线程、并发与线程池并发编程是Java基础里的重头戏笔试出现频率极高。网易的卷子里至少会有两三道题涉及线程同步、锁、线程池参数。其中我最推荐彻底搞懂的是线程池。线程池的考察点是标准化的核心线程数、最大线程数、空闲存活时间、工作队列、拒绝策略这五要素必须背得滚瓜烂熟。执行流程也要能讲清楚当提交一个任务时如果当前线程数小于核心线程数创建新线程执行如果大于等于核心线程数且队列未满放入队列如果队列满了且当前线程数小于最大线程数创建新线程如果线程数已经达到最大执行拒绝策略。网易可能会给你一组具体参数然后问“当第N个任务到来时会发生什么”这种题就是考执行流程别记混。Synchronized和ReentrantLock的区别也是高频考点。先说结论两者都是可重入锁但synchronized是JVM层面的关键字自动加锁释放锁非公平ReentrantLock是API层面的实现支持公平锁、可中断、可超时、可绑定多个Condition条件。这么多年开发下来我的感受是JDK 1.6之后synchronized经过锁升级偏向锁→轻量级锁→重量级锁优化大多数场景性能已经不输ReentrantLock所以笔试如果你是答“两者性能谁更好”要说明“分场景现代JDK下差距不大”。ThreadLocal在Android里尤其重要因为Looper就是通过ThreadLocal来保证每个线程只有一个Looper实例的。笔试考ThreadLocal通常是这么考的ThreadLocal的底层结构是什么为什么ThreadLocalMap的key是弱引用会有什么问题答案主线是每个Thread内部有一个ThreadLocalMap以ThreadLocal为key、以你set的对象为valuekey用弱引用是为了避免ThreadLocal对象无法被GC但value是强引用所以如果ThreadLocal被回收而value还在就会出现key为null但value不为null的脏数据。Android的Handler机制里主线程Looper生命周期和进程一样长所以一般没有泄漏问题但如果你在子线程用ThreadLocal并且忘记remove就要小心内存泄漏了。2.4 Android四大组件与启动模式Android组件的考察在整套卷子里占了相当大的比重。Activity、Service、BroadcastReceiver、ContentProvider这四大组件在网易的选择题里几乎都会出现。最容易丢分的是各种“场景判断”题比如“Activity A启动BB设置singleTask请问A和B的生命周期回调顺序”。对启动模式我总结了一套自己的记忆方法。Standard是每次都新建实例少数场景会用比如普通页面跳转singleTop是栈顶复用适合接收推送通知后跳转的页面避免连续点击通知导致页面堆叠singleTask是栈内复用适合App主页保证整个App只有一个主页实例且会清理掉它上面的所有ActivitysingleInstance是独立任务栈适合需要全局唯一的页面比如来电界面、系统级别的弹窗。要特别注意singleTask启动已有实例时的回调顺序会先调用现有实例的onNewIntent然后onRestart、onStart、onResume而原来栈内它上面的Activity会被销毁。除了启动模式Activity生命周期在异常情况下的表现也是易考点。比如屏幕旋转时Activity会被销毁重建onSaveInstanceState在onPause之后onStop之前调用恢复数据在onRestoreInstanceState或onCreate的savedInstanceState里取。网易考过一道题问“在onPause里执行耗时操作是否合理”答案肯定是不合理因为A的onPause执行完才会让B显示如果耗时过长会影响页面切换体验正确的做法是onStop或更晚阶段处理。Service方面笔试题比较喜欢考启动方式和绑定方式的区别。startService启动的Service与启动者无绑定关系即使启动者销毁Service还能继续在后台运行bindService则绑定生命周期绑定者销毁时如果没有任何绑定关系Service会自动销毁。同时要了解onStartCommand的返回值START_STICKY、START_NOT_STICKY、START_REDELIVER_INTENT的区别网易出现过把STICKY和REDELIVER_INTENT混在一起考的题目。BroadcastReceiver和ContentProvider相对考得少但ContentProvider有一个必知必会点ContentProvider的启动与App进程的关系。如果App进程没有启动通过ContentProvider访问数据时系统会先创建目标App的进程然后实例化ContentProvider再执行query等操作。这个知识点在考“ContentProvider与Application的onCreate谁先执行”时就会用上。另外Android 8.0之后对隐式广播做了限制很多静态注册的广播不再能通过隐式Intent收到这套题虽然是2018年的但正好赶上这个变化我用的是Android官方适配说明里的内容读者要留意版本差异。2.5 Handler消息机制与LooperHandler这一块可以说是网易Android笔试卷中的“必考题”而且是一考就考好几道的那种。我从真题里总结核心考点集中在五个方向Handler/Looper/MessageQueue三者关系、主线程为什么不会因Looper死循环而ANR、MessageQueue的阻塞与唤醒机制、同步屏障与异步消息、Handler内存泄漏与正确写法。先说三者关系。每个线程只要调用了Looper.prepare就会创建一个唯一的LooperLooper构造时会创建MessageQueue。Handler在创建时从当前线程取出Looper所以Handler默认绑定的是“创建它的线程”。Handler通过sendMessage把Message放进MessageQueueLooper通过loop方法不断从队列取消息最终回调Handler的dispatchMessage和handleMessage。记住一个口诀Handler负责发送和处理Looper负责循环取消息MessageQueue负责存储。主线程的Looper死循环为什么不会卡死主线程这个问题几乎每次面试和笔试都会遇到。答案要从两个层面讲。第一Looper.loop是一个for无限循环当队列没有消息时MessageQueue的next方法会调用nativePollOnce阻塞当前线程这时候主线程是休眠状态不消耗CPU资源所以不会造成卡顿。第二Android所有UI绘制、事件分发、四大组件切换本质上都是通过向主线程MessageQueue发消息来驱动的也就是说主线程的工作方式就是“消息循环”如果没有这个循环系统反而无法工作。可以类比成一家餐厅只有一个服务员他不能离开餐厅没客人时就在柜台趴着休息一旦有客人进来他能马上响应。MessageQueue的阻塞与唤醒底层用的是Linux的epoll机制。nativePollOnce传入超时时间如果超时返回或者有新的消息写入队列就会通过nativeWake唤醒。这个知识点顺带解释了为什么Handler.postDelayed是“精准的延时”而不是“开个线程sleep”——延时消息并不是真的在时间到了才放进队列而是放进队列后计算好时间点到时候从队头取出。如果队头是一个还没到时间的延时消息next就会计算剩余时间并进入epoll等待有新的消息进来时会重新计算唤醒时间。关于Handler内存泄漏笔试和面试都爱问。原因很明确非静态内部类Handler默认持有外部Activity的强引用如果消息在队列里延迟执行而Activity已经finishActivity就无法被GC回收。解决方案是使用静态内部类继承Handler然后持有Activity的弱引用在onDestroy时移除所有消息和回调。注意移除的时候要分别调用removeCallbacksAndMessages(null)和removeMessages两者针对的对象不同前者移除所有Runnable和Message后者只移除指定what的消息。2.6 Context相关与Android资源管理Context是Android开发里最基础也最容易讲不清楚的概念。网易的试卷里出现过“Context的继承结构是什么”这类题。Activity、Service、Application都间接继承自Context但它们的Context类型不同Activity和Service继承ContextWrapper而ContextWrapper内部又持有一个ContextImpl实例真正干活的是ContextImpl。笔试喜欢考的辅助场景是“getApplicationContext和Activity.this有什么区别什么时候能用哪个”。比如弹Toast可以用ApplicationContext但启动一个Activity就必须用Activity的Context或者在新任务栈里加FLAG_ACTIVITY_NEW_TASK。还有一个容易忽略的点LayoutInflater.from(context)和context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)最终拿到的是同一个实例但它在不同Context下使用时的主题资源会有所不同这跟ContextImpl里mThemeResource有关系。3. 算法编程题思路与手写代码技巧3.1 网易笔试算法题高频题型与解题模板网易Android岗的算法题从历年情况来看集中在数组处理、字符串处理、链表操作和简单动态规划上。2018年这套卷子里有两道题我记得一道是“判断一个字符串能否通过调整字符顺序变成回文串”另一道是“实现一个简单的LRU缓存支持get和put操作”。第一道题核心思路是用哈希表统计每个字符出现次数然后判断奇数次的字符个数是否大于1。大于1说明无法构成回文串等于0或1则可以。这类题目的变体还包括“构造回文串并输出字典序最小的结果”那就需要进一步处理排序和双端队列了。第二道题LRU缓存就更有意思了它既能考算法和数据结构又能体现实际开发中的资源淘汰策略Android里的LruCache也是据此设计的。笔试时用LinkedHashMap来实现是最快的重写removeEldestEntry方法即可但如果面试官追问底层原理你必须知道哈希表加双向链表的组合方案。针对高频题型我建议准备几个代码模板双指针模板处理数组有序、链表环判断、回文串题目。滑动窗口模板处理子串、子数组问题。单调栈模板处理下一个更大元素类型。递归转迭代模板二叉树遍历、链表反转。这些模板不需要背很多会套就行。网易的笔试算法部分核心目的是筛选出“基本功扎实、能写出可运行代码”的候选人不会刻意出偏题怪题。3.2 笔试环境下的输入输出与时间管理很多人平时刷题用LeetCode习惯了直接写函数体但网易的笔试系统是要求自己处理输入输出的。我记得当时用的是牛客网或者其他在线笔试平台输入是标准输入输出是标准输出第一行可能是测试用例组数然后每组数据单独一行。这个差距导致很多LeetCode刷得很6的同学在笔试时直接懵了写出来的代码没处理输入输出一分拿不到。我强烈建议在校招季之前专门花一周时间练习“从标准输入读取、解析、输出”的能力。Java写笔试题目时推荐用BufferedReader加StringTokenizer或者split来处理不要用Scanner因为Scanner在读取大量数据时性能明显不足。如果输入是整数直接Integer.parseInt处理如果输入包含字符串注意可能带有空格或者空行要做好trim处理。输出时用StringBuilder把结果拼接好最终一次性打印避免多次调用System.out.println否则数据量大的时候会拖慢程序极端情况下可能被判超时。编程题的阅卷逻辑通常是“多组数据都通过才算对”所以边界条件一定要想清楚。比如输入数组为空的场景、只有一个元素的场景、字符串长度为负数的不可能情况、两个整数相加可能溢出的情况。写出这些边界条件的判断既能提高通过率也在向阅卷系统展示你思路严密。3.3 手写代码的考察点与评分标准笔试系统一般不会人工看你的代码只看输出结果。但部分校招批次在编程题之后还会有问答或者结合你的代码进行追问。所以代码本身的风格仍然有影响。手写代码时变量命名要语义化比如用left、right、index不要用a、b、c这种无意义的名字逻辑要尽量精简避免层层嵌套的if关键的算法步骤可以加注释但不要为了注释而注释。网易这种体量的公司笔试筛选的是硬实力代码规范上不会卡得太死但在几乎相同的解法之间干净整洁的代码更容易在后续面试环节被面试官问到时给你加分。提示编程题如果题目没有明确要求优先选择你最有把握的算法而不是最优算法。笔试环境下时间有限暴力解法如果能通过就跑暴力然后留时间做第二道题。每一分都拿到才是最重要的。4. 网络、操作系统与数据库基础4.1 TCP/IP与HTTP网络的Android开发Android开发对网络的要求并不低因为App的核心功能基本都是靠网络完成的。网易笔试卷对网络的考察主要集中在TCP和HTTP。TCP的三次握手、四次挥手几乎是必考题但笔试不会让你画流程图而是用选择题考察“某一状态下发生了什么”。比如“TCP连接建立过程中客户端发送SYN之后所处的状态是什么”答案是SYN_SENT服务器端收到SYN后变成SYN_RCVD然后双方进入ESTABLISHED。HTTP方面网易2018年的题里涉及了HTTP和HTTPS的区别、HTTP的请求方法以及状态码。记住一个核心区别HTTPS在HTTP和TCP之间加了一层TLS/SSL加密协议握手过程需要交换证书、协商密钥所以连接建立速度比HTTP慢但数据是加密的。状态码要重点记200表示成功、301永久重定向、302临时重定向、304未修改可用于缓存协商、400客户端错误、401未认证、403禁止访问、404资源不存在、500服务端内部错误、502网关错误、503服务暂不可用。Android网络开发还有一个容易被笔试考到的点OkHttp的拦截器机制和连接池复用。虽然这套题是2018年的当时OkHttp已经是主流但笔试很少直接考框架内部原理更多还是考HTTP协议本身。所以备考时先把协议层搞懂框架层面试时再深挖。4.2 进程、线程与Android的进程模型操作系统进程与线程的题目在网易卷子里会以一种“Android特色”的方式出现。比如“Android中进程的优先级分为几个等级哪个级别的进程最容易被系统杀死”。这里涉及Android的进程回收机制前台进程、可见进程、服务进程、后台进程、空进程回收优先级从低到高。空进程会最先被回收所以很多App坚持做“进程保活”本质上是在和服务系统拼优先级。Android的IPC进程间通信也是高频知识点。Android系统里最核心的IPC方式就是Binder笔试喜欢考“一次Binder通信大概需要几次内存拷贝”以及“Binder相对于传统IPC的优势”。答案是一次拷贝传统IPC通常是两次。原因在于Binder通过内核映射区实现了数据共享发送方数据先拷贝到内核空间接收方再映射读取不需要额外从内核拷贝到接收方用户空间。这部分如果觉得抽象可以类比成两个人传文件传统方式是先把文件拷到U盘内核再把U盘插到接收方机器上拷过去两次拷贝Binder方式是直接把文件放到共享网盘两个人同时访问同一个文件只需要一次写入过程。4.3 SQLite与数据库迁移数据库在笔试中占比不高但出现在多选题中的概率还是有的。主要知识点包括SQLite支持的数据类型NULL、INTEGER、REAL、TEXT、BLOB、主键与自增主键、索引的作用与代价、事务的ACID特性。网易考过这样一道题SQLite中哪些语句会触发隐式事务。答案是把多个写操作放在一个事务里能大幅提升性能因为每条SQL语句默认都会自动开启和提交事务而事务的磁盘I/O消耗很大。在实际开发中批量插入几百条数据时如果不手动开启事务可能会因为频繁写盘导致主线程卡顿所以Room等框架都会默认帮你在事务中执行批量操作。关于数据库升级笔试问“数据库版本从1升到2onUpgrade方法的参数是什么意思”的概率很高。oldVersion和newVersion分别指的是旧数据库版本号和新数据库版本号实际开发中每次表结构变化都要在onUpgrade里写对应的迁移逻辑比如判断oldVersion小于2时执行ALTER TABLE等。5. 性能优化与架构设计题目5.1 内存泄漏常见场景与检测手段前面在Handler部分已经讲了Handler导致的内存泄漏但网易的卷子对内存泄漏的整体考察远不止这一种。还有一些典型场景经常出现在多选里Activity被静态集合强引用、匿名内部类持有外部引用、资源Cursor、IO流未关闭、单例模式持有Activity的Context、ListView适配器里的ViewHolder没有正确复用这题比较老但在掌握原理上有价值、Bitmap未回收等。笔试如果问到“如何检测内存泄漏”标准回答路线是先用Android Studio的Memory Profiler观察内存抖动和堆内存趋势再用LeakCanary做自动化检测定位到具体泄漏引用链。LeakCanary的原理要理解通过Application注册ActivityLifecycleCallbacks监控Activity的onDestroy然后利用弱引用和ReferenceQueue判断对象是否被回收如果迟迟没有回收就手动触发一次GC并dump堆内存最后通过HaHa库解析堆栈找出强引用链。这里我要强调一个常被忽略的点泄漏并不一定发生在Activity上还可能是View、Bitmap、自定义View里的Drawable甚至是Fragment。检测手段都一样但修复方案不同。笔试填选项时看到“仅靠LeakCanary就一定能解决所有泄漏”这种绝对化表述直接排除。5.2 布局性能与过度绘制优化Android的UI渲染性能是校招笔试关注的重点之一。网易出现过“如何减少过度绘制”“哪些操作会导致掉帧”这类选择或判断。核心认知是屏幕每个像素点绘制多次就是过度绘制打开的开发者选项里的“显示布局边界”可以查看颜色越红说明绘制层数越多。优化手段包括减少不必要的背景绘制尤其是父布局和子布局同时设置背景色、用ConstraintLayout减少布局层级、使用include和merge标签复用布局、ViewStub延迟加载不需要立即显示的视图、RecyclerView复用机制正确使用不要在onBindViewHolder中创建新对象。笔试里经常混淆的还有invalidate和requestLayout。invalidate只会触发重绘onDraw不会重新测量和布局requestLayout会触发measure和layout如果视图的尺寸或位置发生变化才应该调用。理解这个区别对性能优化很有帮助因为频繁的requestLayout意味着大量measure这在复杂布局里是很昂贵的操作。5.3 图片加载与三级缓存原理图片加载框架是Android笔试的常客尤其是Glide。网易2018年的卷子虽然没有直接考“Glide的源码流程”但考了“三级缓存策略”“内存缓存和磁盘缓存的区别”“为什么RecyclerView滑动时Glide能加载得更流畅”。三级缓存指的是内存缓存、磁盘缓存、网络加载。读取顺序先从内存读读不到再从磁盘读还读不到就发网络请求。写缓存顺序网络图片先写入磁盘再解码到内存缓存供下次快速读取。Glide默认用LruCache做内存缓存用DiskLruCache做磁盘缓存。Glide的一个重要特色是绑定生命周期通过RequestManager监听Activity或Fragment的生命周期在页面不可见时暂停加载可见时恢复加载。这可以大幅节省资源。笔试考到“Glide和Picasso的对比”时常见考点是Glide按Activity生命周期加载、支持GIF、磁盘缓存策略更灵活而Picasso体积更小但只缓存全尺寸图片。此外用Glide加载图片时如果图片URL没变默认情况下是不会重新加载的需要用到signature或设置diskCacheStrategy。5.4 MVC、MVP与MVVM以及代码规范架构模式的考察在笔试试卷里通常以选择题或简答题出现。我记得网易有一道题是“MVP模式相对于MVC的优势是什么”四个选项里正确答案是“将UI逻辑和业务逻辑分离View层更轻更易单元测试”干扰项包括“开发速度最快”“完全没有内存泄漏问题”等。MVC在Android里的痛点Activity同时承担View和Controller的职责代码一多就变成“上帝类”难以维护和测试。MVP把业务逻辑抽到PresenterActivity/Fragment只负责View的展示和事件转发View和Presenter通过接口通信因此Presenter可以脱离Android环境做单元测试。MVVM则是在MVP基础上引入数据驱动View和ViewModel之间通过LiveData或DataBinding双向绑定进一步减少手动控制逻辑。笔试不会要求你写一个完整的MVP框架但可能会让你阅读一段代码判断它属于哪种架构或者指出这种架构存在什么问题。我的建议是把三种架构的核心关系图记清楚并把“Presenter或ViewModel在Activity销毁后持有的View引用会造成泄漏”这个坑记牢。MVVM的解决方式是LiveData感知生命周期但即使如此在ViewModel里持有Activity的Context仍然是被禁止的。6. 备考路线、刷题方法与笔试避坑6.1 从零开始三个月的备考时间线结合我对这套题和整个秋招的复习经验如果现在还有三个月时间我建议这样分阶段准备第一个月主攻Java基础和Android基础。Java方面把集合源码、并发、JVM内存与GC过一遍配合剑指Offer的经典题练习Android方面按四大组件、Handler、启动模式、消息机制、布局与绘制的顺序吃透。这个月不用急着刷笔试真题先把知识点系统化。第二个月开始刷真题和LeetCode。LeetCode以数组、链表、字符串、二叉树、动态规划为主每天两到三道复习一遍比开新题更重要。同时每周至少安排一次完整的笔试模拟控制在90分钟锻炼时间分配和心态。同时注意整理错题把每次笔试的错题按知识点归类找到自己最薄弱的模块重点补。第三个月回归基础和查漏补缺。网易这类公司笔试风格稳定考来考去还是那些知识但你不知道它会从哪个细节切入。这时候把所有笔记和错题重新过一遍重点看那些“易混淆”“容易记错”的点。比如Activity的四个启动模式对应的栈变化、HashMap在并发环境下的表现、Handler消息队列的阻塞唤醒机制这些高频细节值得反复背。6.2 高效的刷题与复盘方法我见过很多同学刷题只追求数量一天刷十道半个月后回头一看全忘光了。刷题的正确方式应该是“三遍法”。第一遍独立做做不出来就看题解看懂后合上题解重新写一遍第二遍隔一天后重新做检验自己是不是真的会了第三遍一周后再做速度和边界条件都要过关。这个方法看着慢实际效率极高能把一道题的解题思路内化成自己的。笔试真题的复盘比刷题更重要。每套卷子做完不要只对完答案就扔要花至少两倍的时间去分析。选择题里每一个错误选项都要搞清楚它错在哪里是概念混淆还是场景不匹配还是绝对化表述。编程题即使跑对了也看看官方题解里的更优解法想一想自己的解法有没有隐藏的边界问题。我当时准备了一个笔记本专门记录“为什么错”到后期翻看时帮助特别大。6.3 笔试实战中的避坑技巧最后说几个实战中容易踩的坑这些全是我亲身经历。第一提前检查笔试环境。校招笔试一般用牛客、赛码等在线平台有些平台要求用特定浏览器有些要开启摄像头监控。提前一天登录测试环境确认摄像头、麦克风、网络都没有问题。临时换电脑是很致命的因为在线编程的体验很难在短时间内适应。第二注意输入输出的坑。在线笔试要求从标准输入读数据不要写死测试用例。有些题是一组数据有些题是多组数据一定要仔细读题。输出格式也要严格比如题目要求每个结果占一行就不要多打印空行也不要输出多余的文字提示。第三选择题不要空着。网易的笔试选择题一般没有倒扣分机制所以不管会做不会做都要选一个。多选题如果实在拿不准宁可少选也不要多选因为多选漏选通常都算错少选可能还能拿一点分。第四拿到卷子先分配时间。前面已经强调过再重复一次先扫全卷标记编程题选择题快做编程题要确保有时间写。编程题即使最后没做完写出思路和关键代码也能拿到部分分白卷就彻底没戏了。第五不要在代码里暴露出真实的个人习惯或公司信息。笔试代码的注释、变量名用正常命名就好别写跟项目相关的敏感内容一方面是不专业另一方面也可能被认为是在使用外部资源存在违规风险。这些经验是我在2018年那场秋招里实打实踩坑踩出来的。网易的这套卷子难度中等偏上覆盖面特别完整我自己做完之后最大的感受是你永远不知道试卷会考哪个细节所以唯一保险的办法就是把基础打牢把原理吃透而不是指望背一堆“标准答案”。现在再回头看那段时间高强度刷题、复盘、写总结的经历不仅仅帮我拿到了几个offer也把我对Android整个体系的理解拔高了一个层次。这套题准备过之后后面面对其他公司的笔试题心里就踏实很多了。