ARTICLE DETAIL

资讯详情

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

360校招Android笔试客观题全解析:核心考点与答题策略

360校招Android笔试客观题全解析:核心考点与答题策略 作为在Android开发这条路上摸爬滚打了十来年的老兵看到“360公司-2019校招笔试-Android开发工程师客观题合集”这样的标题第一反应是熟悉第二反应是感慨。熟悉的是这些题目的考察范围这么多年其实一直很稳定感慨的是依然能看到大量候选人在客观题上栽跟头——不是不会而是被“客观题”三个字迷惑了以为凭感觉就能做对。这份合集的价值不在于题目本身而在于它把Android开发最核心的基础能力用选择题的形式重新梳理了一遍。这篇文章我会从出题逻辑、核心知识点、答题策略和常见误区四个维度展开尽量还原当年我做这套题、以及后来帮团队看校招卷子时的真实思考过程。1. 客观题合集的含金量与出题逻辑拆解1.1 客观题在Android校招里到底考什么很多刚准备校招的同学容易把客观题理解成“送分题”觉得选择题嘛蒙也有四分之一的正确率。但真实情况恰恰相反Android方向的客观题往往是整张卷子里筛选率最高的部分尤其是360这类互联网公司的校招笔试。原因很简单一道客观题可以同时覆盖三四个知识点而且每个选项都是一个独立的考点。比如一道关于Activity启动模式的题表面上考的是standard、singleTop、singleTask、singleInstance四种模式的区别但四个选项里可能混入了Context的启动Flag、onNewIntent回调时机、返回栈的压栈顺序甚至taskAffinity的配置。如果对知识体系没有整体认知很容易被某个看起来“熟悉”的选项带走。从我这些年看校招卷子的经验来说客观题的设计逻辑基本遵循三条主线第一考察“知其所以然”。比如Handler机制会同时考Looper在子线程中怎么创建、MessageQueue阻塞与唤醒的原理、IdleHandler的触发时机而不只是问“Handler能不能在子线程创建”。第二考察“边界条件”。比如onSaveInstanceState的调用时机、Process.killProcess后是否走onDestroy、ContentProvider的启动顺序这些都是平时敲代码很少碰到、但面试官非常爱出的边界场景。第三考察“横向对比”。比如Handler、AsyncTask、HandlerThread、IntentService、协程这几种异步方案客观题会用一道题把它们的适用场景、线程切换方式、生命周期耦合度全部串起来。所以这份360的客观题合集核心价值不在于告诉你“哪几个选项是对的”而在于帮你把Android知识网络里的节点一个个排查一遍查漏补缺。1.2 为什么说客观题比主观题更难准备主观题比如写一道算法、设计一个架构答不出来至少还能写点思路阅卷人多少会给点辛苦分。但客观题没有中间态对就是对错就是错而且错一道题往往意味着某个知识盲区被精准扫到了。我见过太多这样的案例一个同学项目经验很丰富做过性能优化、自定义View、JNI聊起来头头是道结果校招笔试的客观题正确率不到六成。复盘下来问题不在于他能力不行而在于他习惯了“够用就行”的学习方式。比如Handler机制他知道Handler.post最终会走到Runnable的run方法但笔试会问“MessageQueue.next()在没有消息时为什么不会ANR”这需要理解nativePollOnce和epoll机制平时不深挖到这一层就答不上来。客观题难准备的另一个原因是它的“反直觉”设计。出题人特别喜欢设置那些“理论上合规但实践上踩坑”的选项。比如问你Bundle能传哪些类型会放一个“Bitmap可以直接传吗”的选项很多同学觉得能传因为确实能通过Bundle传递Bitmap但实际上系统会报TransactionTooLargeException而且这个异常是运行时才能发现的。这类陷阱题单靠刷题背答案是记不住的必须理解背后的Binder事务大小限制机制。换句话说客观题是检验一个Android开发者知识深度的标尺。准备客观题的过程本质上是在把日常开发中那些“知其然不知其所以然”的部分补齐这才是这份合集最值得花时间的地方。2. 必考的Android核心知识体系盘点2.1 四大组件与生命周期客观题的基石无论哪家公司的校招卷四大组件都占了客观题的相当比例。这一块看着基础但出题人把它玩出了花。先说说Activity。除了启动模式和生命周期回调顺序这两个必考点360这套卷子里比较有代表性的考察方向是异常情况下的生命周期。比如屏幕旋转时Activity是怎么重建的onSaveInstanceState在什么时候调用、什么时候不调用这些都是容易混淆的点。关键在于记住一个原则凡是系统可能会回收你的Activity的场景都会在销毁前调用onSaveInstanceState比如按Home键、按电源键、屏幕旋转、内存不足被系统杀死。但有一种情况不会调用——你没有显式调用finish()而直接按返回键退出这时候系统明确知道你是主动关闭不会帮你保存状态。再看Service校招高频考点是startService和bindService共存时的生命周期以及多次startService时onStartCommand的调用次数。还有个几乎每套题都会出现的点Service的onBind和onUnbind方法以及从Android O开始后台Service的启动限制。Android 8.0之后应用处于后台时不能随意创建Service必须用startForegroundService并尽快调用startForeground这个变化在校招笔试里反复出现。BroadcastReceiver考的更多是注册方式。动态注册和静态注册的分界线以及Android 8.0之后对隐式广播的限制。这些内容如果平时不做系统级应用很难注意到但对于校招笔试来说恰恰是送分题背下来就能拿分。ContentProvider这个点校招笔试通常不会考得太深但会和Binder机制结合起来。比如问你ContentProvider的调用过程其实是想考察你对Binder的原理理解因为ContentProvider的跨进程访问本质上是基于Binder的而且ContentProvider的实例是在目标进程的Application创建之后才创建的。注意这里有一个容易被忽略的知识点进程的入口不一定是你写的类ContentProvider会在Application.onCreate之前完成初始化这就意味着你在ContentProvider.onCreate里做的初始化操作时机比Application还早。2.2 Handler与消息机制每次笔试几乎必现在Android校招笔试里Handler相关题目出现的频率是100%级别可以说只要考Android就没有不考Handler的。为什么因为它同时牵扯到线程、内存、消息队列、系统IPC等多层知识。最基础的考法是问“在子线程中创建Handler会有什么问题”。答案会CRASH但你得能说出来为什么——因为主线程在启动时已经调用了Looper.prepareMainLooper()而子线程没有Looper默认的Handler构造器会用Looper.myLooper()去拿当前线程的Looper结果是null于是抛异常。那怎么解决在子线程中手动执行Looper.prepare()然后new Handler()最后调用Looper.loop()。这套题换个马甲再问你MessageQueue和Looper是一对一的关系吗答案是Looper和线程一一对应一个线程只有一个Looper而MessageQueue是Looper里的一个成员也是一个。但要小心Message里的Handler不是一一对应的一个Handler可以处理多个Message同一个Message在不同线程里setTarget的结果也不同做题时别被绕进去。另一类高频考点是Handler内存泄漏。比如Activity里声明了一个内部Handler类然后postDelay了一个Message此时如果用户退出页面由于MessageQueue持有这个MessageMessage持有HandlerHandler持有外部Activity的引用就形成了一个完整的泄漏链。这类题不仅考你“会不会泄漏”还考你怎么修复——静态内部类加弱引用以及在onDestroy里removeCallbacksAndMessages(null)。还有一类进阶考法把Handler和ANR机制结合起来。问为什么主线程的MessageQueue被阻塞时不会立刻ANR而是过一段时间才弹出ANR对话框。这需要理解两点第一主线程的Looper.loop()在调用next()时会进入阻塞状态等待新消息第二系统会通过Handler往你所在的应用进程发一个延迟消息比如10秒后执行如果主线程在规定时间内没有处理完之前的消息这个延迟消息就会被ANR对话框弹出拦截。因为发送的是消息所以不会造成死锁但会造成卡顿和ANR。2.3 View绘制与事件分发考察应用层功力360这套卷子里的View部分是拉开差距的地方。一般的题目问onDraw、onMeasure、onLayout调用顺序稍微进阶的会问dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent的传递规则。但真正有区分度的是把自定义View和事件分发放在一起考。比如给你一个场景一个LinearLayout里有一个Button你在LinearLayout的dispatchTouchEvent里return true然后点Button问Button能不能收到点击事件。答案是Button完全不会收到任何事件因为LinearLayout在dispatchTouchEvent阶段就消费了事件事件根本不会向下分发。这类题考察的不再是死记硬背而是对事件分发机制的实时推导能力。View这一块还有一个经常出现在客观题里的点请求重新布局的触发方式。invalidate()和requestLayout()的区别是高频考题。invalidate只会触发onDraw不会触发onMeasure和onLayoutrequestLayout则会触发完整的onMeasure、onLayout和onDraw流程。如果对一个TextView只改变文本内容而不改变宽高用invalidate就够了因为不重新测量布局。关于屏幕适配的题目也值得注意尤其是密度相关的计算。dp转px的公式是px dp * (density / 160)但笔试经常会考不同实际设备上的计算。这里有个很容易踩的坑xxxhdpi对应的density是480即densityDpi480它的缩放比例是3.0而ldpi、mdpi、hdpi、xhdpi、xxhdpi分别对应0.75、1.0、1.5、2.0、3.0。有些题目会故意把“基线密度是160dpi”这个概念和“mdpi对应160dpi”混在一起让你算错结果。3. 典型客观题场景与答题思路实录3.1 一道经典的Activity启动模式题目怎么答我拿一道360这套卷子里比较有代表性的题目来还原一下真实做题过程。题目大意为一个应用中Activity A启动Activity B而B在Manifest里配置为singleTask模式同时启动了另一个应用里的Activity C此时系统分别做了什么拿到这道题正确的做法是先画返回栈把所有Activity的位置弄清楚。A启动B时由于B是singleTask系统会先去查找当前任务栈里有没有B的实例。没有所以直接创建B并压栈。B再启动CC是另一个应用里的Activity注意这里启动C时涉及跨进程的任务栈切换C会进入它所属应用的任务栈。那么问题来了如果此时B的taskAffinity被设置为与C相同的任务栈B和C会被放在同一个栈里吗答案是B启动C时系统会为C寻找合适的任务栈而这个栈的affinity值必须和C的taskAffinity匹配。如果B的taskAffinity和C相同那么C会复用B所在的任务栈如果不同系统会新建一个任务栈。这个细节非常容易错因为很多人只记住了singleTask会创建新任务栈完全忘了taskAffinity才是决定是否复用栈的关键。这类题想拿分关键是把概念梳理成一个推导链先看启动模式再看Intent里是否带了FLAG_ACTIVITY_NEW_TASK接着看taskAffinity属性和实际栈的匹配情况。这四个因素任何一个变了结果都完全不同。3.2 内存泄漏类选择题的判断套路内存泄漏是Android校招必考主题客观题里出现频率极高。360这套集子里的内存泄漏题基本覆盖了开发中常见的几种场景。第一种Handler造成的内存泄漏前面已经说过关键是MessageQueueMessageHandlerActivity这条引用链。第二种静态变量持有Activity或View比如把Context存到static集合里只要App在跑这个引用就一直在Activity没法回收必须用WeakReference或及时remove。第三种注册了监听器或广播接收器但没注销比如在onResume里registerReceiver忘了在onPause里unregisterReceiver泄漏就产生了。第四种单例模式持有引用常见的错误是单例里存了一个View或者Context参数解决办法是使用ApplicationContext。笔试里还有一种比较容易出错的是问你“FragmentTransaction的commit和commitAllowingStateLoss有什么区别”。这不是严格意义上的内存泄漏题但属于生命周期管理范畴。commit会检查当前状态如果宿主Activity已经执行了onSaveInstanceState下次恢复时再执行commit就会抛IllegalStateException而commitAllowingStateLoss不检查不会抛异常但可能有状态丢失。在选择题里你要选的是“哪个场景该用哪个方法”而不是简单说哪个好。作答内存泄漏题的核心思路是看引用链跟着一个对象从创建到使用到销毁哪里断开不了哪里就是泄漏点。如果能形成这种思维习惯选择题里哪怕某个选项描述得很隐晦也能快速判断对错。3.3 多线程与进程通信知识点的常见陷阱多线程这块客观题特别喜欢考线程和进程的边界。有个经典陷阱题一个Android应用里创建了两个子线程问这两个子线程是否共享同一个Application实例答案是共享因为Application属于进程级别进程内所有线程共享同一个对象这没问题。但如果问“两个线程各创建一个Handler是否共用一个Looper”答案就是否Looper是线程级别的每个线程创建Handler前都要有自己独立的Looper。另一个高频陷阱是AsyncTask、HandlerThread、IntentService的比较。客观题出题方式一般是这样需要在后台执行一个定时任务周期性地更新UI下列哪个方案最合适正确答案是HandlerThread加Handler。AsyncTask虽然能更新UI但它不适合长时间运行的任务尤其是Android 11以后AsyncTask已经被标记为废弃一看到“长时间周期任务”直接排除就行。IntentService的好处是任务执行完后自动销毁但它只能顺序执行任务不支持并发。进程通信这块Binder机制几乎是必考的。客观题里关于Binder的问法会有一次完整的Binder调用需要拷贝几次数据答案是一次。传统IPC一般需要两次拷贝Binder通过mmap在内核空间和用户空间共享一块内存只需要在发送方拷贝一次。这个知识点即使有同学不理解底层实现也应该把结论记下来因为选择题里经常拿来跟传统IPC做对比。另外多进程开发中一个经典坑是每个进程都会创建一次Application实例。如果某个进程里你的Application做了很重的初始化比如加载数据库或SDK就可能拖慢该进程的启动速度。笔试里会问你主进程和子进程同时运行时静态变量是否互通答案是不互通因为每个进程有独立的内存空间和虚拟机实例这也是为什么多进程通信必须靠Binder而不是靠静态变量。4. 笔试临场节奏与易混淆点速查4.1 时间分配与做题顺序的建议校招笔试的客观题一般有30到50道限时大概60到90分钟平均每题只有两分钟左右算上读题时间其实非常紧张。我带过的拿到360 Offer的同学里不少人都强调过同一个策略先做有把握的题不会的先随便选个答案并标记等后面的题做完了再回来细想。为什么这么做因为客观题里经常有那种“第一眼觉得A对但仔细推敲发现C更合理”的题如果死磕一道题后面的简单题反而没时间做。举个例子关于View的invalidate和requestLayout有经验的同学一眼就能选出来但如果你在Binder的拷贝次数那道题上纠结了五分钟可能后面三四个送分题都没时间看了非常可惜。我的建议是按题型优先级来排Java基础题和Android基础题四大组件、Handler、Activity生命周期优先做这些拿分最容易。然后是View体系、进程通信、性能优化相关的中等难度题最后如果有时间再去碰算法和设计模式的题。记住校招笔试的目的是进面试不是满分正确率在70%以上基本都是面试有效候选人了。4.2 高频易混淆知识点对照表为了针对性避免混淆我整理了一份我复盘360和同级别公司校招笔试题时常用的易混点对照表。表格未必覆盖所有题目但常见的坑基本都在里面了。易混淆点关键区别一句话记忆方法Looper vs MessageQueueLooper是消息轮询器MessageQueue是消息存储队列Looper负责不断从Queue里取消息onSaveInstanceState vs onPause前者在异常销毁前保存状态后者是进入后台的普通回调异常时才有前者正常退出不触发invalidate vs requestLayout前者只重绘后者触发重新测量和布局只改外观用invalidate改尺寸用requestLayoutstartService vs bindService前者独立于调用者后者生命周期绑定调用者绑定者没了bindService就断了launchMode vs taskAffinity前者决定实例如何创建后者决定栈如何归属启动模式负责人affinity负责栈onDestroy是否一定会调用不一定系统回收进程时不保证主动finish才保证强制杀进程不保证dp vs didp全称density-independent pixeldi全称device-independent pixel实际指同一个东西笔试里常混用别被绕进去静态注册 vs 动态注册静态注册在Manifest动态注册在代码8.0之后静态注册广受限制这类对照表的最大价值不是背下来而是在刷题过程中遇到混淆时拿来对照。如果你做题时发现某两个概念经常混说明它们有共性利用共性和差异去记忆比单独记每个知识点更牢固。5. 备考复盘中的常见误区与避坑经验5.1 刷题不等于死记硬背很多同学有一个误区觉得笔试客观题就是背题把历年的题目答案背下来就行了。这种思路在校招里基本行不通原因有两个。第一同一道题不会原封不动再出现但出题人会把正确答案和错误选项打乱重排还会在选项里偷偷增加一个“看起来对但细节错误”的选项。如果只背答案遇到改动过的选项就懵了。第二更关键的是客观题知识点是连成网络的一道题能带出四个知识点一道题背不下来意味着这四个知识点都可能有盲区而面试官在后续面试里一定会通过深挖这些盲区来验证你的真实水平。刷题的正确姿势是“一题三刷”。第一遍按考试节奏做一遍标记错题和拿不准的题。第二遍不要直接看答案而是把自己对每个选项的推导过程写出来比如选了A是因为“B的onNewIntent时机描述错了C的任务栈归属分析有遗漏D的Flag冲突没考虑”。第三遍复习时重点看推导过程里卡壳的知识点回归源码和官方文档去验证而不是只看正确答案是什么。5.2 从笔试到面试客观题错题怎么转化这是我最想强调的一点。客观题的价值不止在于笔试得分更在于它是面试的“题库”。360这类公司面试官问的问题很多都是从笔试客观题里延伸出来的。比如你笔试里做错了“singleTask启动模式”那道题面试时面试官可能会问“你在项目里实际用到过singleTask或singleTop吗当时为什么选它”这时候如果你只背了概念就会接不上话。但如果你复盘时想的是“这个模式适合做主页面避免重复创建”并且能结合自己项目里的一些导航需求来讲面试官就会认为你是真正理解了。所以备考时每做错一道客观题建议给自己额外布置两个任务第一把这个知识点用一句话讲清楚能讲到让一个非Android开发也听得懂的程度第二想一个真实场景这个知识点在什么业务下会派上用场。比如ContentProvider跨进程访问可以关联到“多个应用之间共享数据时为什么不用文件而是用ContentProvider”再比如内存泄漏场景可以关联到“埋点上报库的生命周期与页面退出时的解绑”。5.3 环境与工具链的准备也要提前做这里有个很多人会忽略的细节笔试系统如果是在线编程环境可能会要求你本地配置Android开发环境。2019年那会儿主要用Eclipse和Android Studio现在基本统一是Android Studio了但不管哪一年“本地环境能不能跑起来”都会影响你的心态和节奏。建议校招前一个月就把开发环境稳定下来Android Studio版本、AGP版本、JDK版本、Gradle版本都对齐至少保证一个Hello World能秒级编译。不要等到笔试当天才新装一个Android Studio遇到依赖下载慢或者SDK缺失的情况心态很容易崩。热词里提到的R8、APEX这类技术虽然偏进阶但如果你在环境配置时顺手理解一下AGP构建流程遇到“构建失败”这类在线编程题时也能更从容地排查。另外现在校招笔试里的客观题往往配合一段代码或日志输出让你推测运行结果。如果本地环境允许调试直接用ADB把代码跑一下是最快的方法如果不允许就靠手推。平时练习时我建议对每个知识点都做一次“手推运行结果”的训练不要一上来就打开IDE验证这样考试时遇到不能调试的环境也不会慌。这里再说一个客观题共有的经验做题时永远把“异常路径”放在前面考虑。Android开发里的崩溃、泄漏、ANR大多数发生在边界场景和异常路径上而不是正常流程上。比如启动一个Activity时如果目标Activity还没完全创建完成此时系统来了个onNewIntent或者用户立刻按了返回键这时候的生命周期是什么样这些才是出题人真正想考的内容。如果把Android开发的知识体系比作一棵树客观题考察的其实是树的根和主干——Java基础、四大组件、Handler、View、进程通信、内存管理这些最底层的东西是否扎得牢。360的这份2019校招客观题合集虽然年份早了一些但Android底层的机制并没有太大的变化它依然是一份很值得静下心来刷一遍的练习题。按照我上面的方法做完这套题收获的不应该只是“我做对了多少道”而是“我发现自己还有哪些概念没有真正理解”。这个过程有点磨人但确实是校招准备里性价比最高的一段路。
返回列表