ARTICLE DETAIL

资讯详情

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

字节跳动2018校招Android真题复盘:核心知识点与面试经验

字节跳动2018校招Android真题复盘:核心知识点与面试经验 字节跳动2018校招Android方向第三批这套题我到现在还留着当时的草稿笔记。那会儿秋招刚结束我把能翻到的面经和真题都刷了一遍发现字节的Android考察思路跟其他大厂有明显区别——不绕弯子、不堆名词每一道题都在追问你“到底有没有真正写过代码、调过Bug”。特别适合正在准备Android校招、或者工作两三年想跳槽的人拿来当自测清单。这篇文章我会按当时的考纲把核心知识点、源码追问和手写题全部拆开讲顺便把我在实际面试中踩过的坑和总结的答题节奏一并复盘。1. 2018年字节跳动校招Android方向的考察思路1.1 为什么这批题值得反复回味2018年字节跳动还在快速扩张期今日头条、抖音都已经起量客户端团队缺人缺得厉害。但缺人不代表放水第三批次的题目反而很典型因为它处在校招中后期题库已经打磨过一轮筛人的标准已经从“会不会背八股”变成了“有没有工程直觉”。我后来回过头看这批题有三个非常鲜明的特点。第一Java基础占比高但从来不问死概念比如JVM内存模型一定会结合“对象在什么时候进入老年代”这种具体场景第二Android部分特别爱问Handler和Binder因为这两个是客户端线程模型和IPC的命脉只要其中一个答不透后面性能优化基本聊不下去第三算法题量不大但难度在线主要考链表、二叉树和动态规划而且要求现场在白板上直接写一边写一边讲思路。所以如果你想拿这批题当复习索引千万不要按目录顺序背而是应该按“Java基础 → Android核心机制 → 性能优化 → 算法手写 → HR面”这条主线去准备。前两轮技术面基本就围绕这条线展开三轮之后的交叉面反而更看重你项目里有没有真实的数据和反思。1.2 我的复习路线与时间投入我当年是提前六周开始准备的前面两周专门过Java基础和并发中间两周啃Android源码和性能优化最后两周刷算法和模拟面试。每天有效学习时间大概七到八个小时周末会拿一整天做整套模拟题。这里有一个很重要的经验字节的面试官很喜欢追问“为什么”所以复习的时候不要只记结论要把每一个机制背后的设计动机搞清楚。比如Handler你不仅要会说Looper在轮询、MessageQueue是链表还要能说出“为什么不用锁来实现阻塞而是用epoll机制”这种深度才是面试官真正想听的。我当时给自己定了一个标准——每个知识点都要能举出一个实际崩溃或性能问题的案例来验证举不出来就说明还没吃透。2. Java与Android基础重难点逐项拆解2.1 JVM内存模型与GC机制字节2018年这套题里JVM相关问题几乎是必考的而且问法很刁。我印象最深的一道是“一个对象从创建到被GC回收在内存里经历了哪些区域”这题看着基础实际要把对象分配、栈上分配尝试、TLAB、Eden区、Survivor区、老年代、Finalizer机制全部串起来说中间漏一环都会被追问到卡壳。我当时的回答思路是分三段讲。第一段说对象创建优先在栈上分配不行就进TLAB再不行才去Eden区第二段说Minor GC经过对象在Eden存活后进入Survivor每次Minor GC年龄加一达到阈值默认15进入老年代但大对象和动态年龄判定也会直接晋升第三段说回收方式老年代一般用标记-整理配合CMS或G1Android这边ART用的是并发标记清除加copying的组合。最后一定要落到Android场景比如Bitmap的native内存分配和Java堆的关系因为面试官多半会顺着这一句往下挖。另外需要重点准备的是类加载机制尤其是双亲委派。字节问过“如果我自己写一个java.lang.String会被加载吗”这种题就是要你答出“不会因为Bootstrap ClassLoader会先加载rt.jar里的标准类”。但更进阶的追问是“Android的ClassLoader体系跟标准JVM有什么不同”这时候要说出PathClassLoader和DexClassLoader的区别以及热修复里为什么用parent null的玩法来绕过双亲委派。2.2 四大组件与Binder通信四大组件是Android面试的底盘2018年这批题尤其爱问Activity的启动模式和生命周期组合。我遇到的一道真题是“Activity A启动模式是singleTaskB是singleTopA启动B再启动A生命周期怎么走”这题看似简单但很多人在“onNewIntent”和“onPause/onStop”的顺序上栽跟头。正确顺序是A启动BA onPause → B onCreate/onStart/onResume → A onStopB再启动A时因为A是singleTask且栈内已有实例会走onNewIntentB onPause → A onNewIntent → A onRestart → A onStart → A onResume → B onStop → B onDestroy。这里有一个值得深挖的点onNewIntent发生的时候onResume已经执行了吗答案是onNewIntent在onRestart之后、onStart之前执行很多人会记错我建议自己写个Demo打印日志验证一遍比背十遍都管用。Service和ContentProvider也要准备。2018年保活还是热点面试官直接问“你怎么让Service不被杀死”我当时给了前台服务加START_STICKY加广播拉活的组合方案但面试官追了一句“这些在国产ROM上还有用吗”这就得老老实实承认厂商限制越来越严进程优先级才是本质。ContentProvider则常和跨进程数据共享连在一起问特别是ContentObserver监听机制有一道题是“如何监听系统相册变化”这个在图片选择器里很常见。Binder是必考中的必考。面试官不问你API怎么调而是问“Binder为什么比Socket高效”“一次Binder调用会拷贝几次数据”。第一个问题要从Linux内核角度讲Binder用mmap把内核缓冲区映射到用户空间只需要一次拷贝而管道和Socket通常需要两次第二个问题要说出mmap映射之后数据从发送端到接收端其实只拷贝到内核缓冲区然后共享给接收端。还经常追问AIDL生成的Stub和Proxy有什么作用以及“oneway”关键字对调用线程模型的影响这些都需要提前模拟过。2.3 Handler消息机制Handler在字节的Android面试里几乎是人手一道因为它串起了线程、内存、性能三块内容。第三批有一道原题是“Handler.postDelayed之后消息是怎么被延迟处理的”这题的考点不是简单的“MessageQueue里排了个队”而是Native层的epoll机制。完整链路是postDelayed会把消息按时间顺序插到MessageQueue的链表里Looper调用next()时如果队头消息还没到时间就计算出剩余时间调用nativePollOnce进入休眠nativePollOnce内部用epoll监听一个事件文件描述符等到超时时间或收到唤醒信号才返回enqueueMessage的时候如果新消息是队头或者时间更早会调用nativeWake去唤醒。所以答案是“延迟不是靠sleep实现的而是靠Native层的定时唤醒”一句话就能跟背答案的人拉开差距。另一个高频追问是“主线程Looper死循环为什么不卡死”。这里要明确区分“阻塞”和“卡顿”Looper在next()里的阻塞是主动挂起等待消息不占CPU也不会导致ANR而卡顿是消息处理耗时超过16ms导致掉帧。当面试官问到这里最好主动提一嘴IdleHandler和SyncBarrier因为这两个点能体现你读过MessageQueue源码而不是只会会用postDelayed。我建议现场画一张Looper、MessageQueue、Handler三者的时序图从sendMessage到dispatchMessage每一步标清线程关系。字节面试官特别喜欢可交互的提问方式你画图的时候他们会顺着图追问细节所以你心里得有“这张图上任何一条线被问到都能展开两分钟”的准备。2.4 集合与并发编程集合这一块字节2018年问得最多的是HashMap。而且不会只问“底层是什么结构”而是直接上场景“HashMap在并发put的时候会有什么问题”你得先答出JDK1.7的头插法会在扩容时形成环、导致死循环再答JDK1.8改成尾插法解决了环但依然会有数据覆盖问题。再往深就是ConcurrentHashMap的分段锁和CAS synchronized实现以及size()方法在高并发下的统计思路。当时还考了ArrayList和LinkedList的取舍以及SparseArray、ArrayMap在Android里的存在意义。我记得追问是“为什么不用HashMap存少量数据”答案是SparseArray底层用两个数组分别存key和value避免自动装箱而且用二分查找在数据量小的时候内存和性能都优于HashMap。并发编程这块synchronized和ReentrantLock的区别是送分题真正的分水岭是“volatile的可见性和指令重排”。面试官给过一个场景“两个线程分别读写一个boolean标志不加volatile会怎样”答案是可能因为CPU缓存导致线程读不到最新值而且JIT可能把循环优化掉。这里要补充说明volatile不能保证原子性只能保证可见性和有序性想要原子操作必须用Atomic类或者锁。线程池也是必问特别是ThreadPoolExecutor核心参数的含义。2018年那批题还考过“如果核心线程数满了会先放队列还是新开线程”答案是先放工作队列队列满了才增加线程到最大线程数再满才走拒绝策略。实际项目里我推荐用自定义线程池而不是Executors的快捷方法因为默认的newFixedThreadPool用的是无界队列高并发下内存容易被打爆。3. 性能优化与Framework层源码级追问3.1 内存泄漏的排查与治理字节的面试官非常看重你“有没有在线上处理过内存问题”所以这一环节通常是送分题也可能是送命题。第三批有一道经典题“Handler持有Activity导致内存泄漏怎么解决”标准答案是匿名内部类改为静态内部类 WeakReference同时在onDestroy里移除回调。但如果只答这一层面试官会继续问“静态内部类加WeakReference就绝对安全了吗”实际上还有两个坑。第一个是Messages队列里如果还有延迟消息即使移除回调Message里的callback或者target仍然会持有Handler而Handler通过WeakReference关联Activity延迟消息期间Activity仍然可能被回收但消息本身还在队列里乱发消息会导致空指针。所以正确做法是onDestroy里同时removeCallbacksAndMessages(null)清空所有消息。第二个是如果你用postDelayed做了倒计时Activity销毁后Message还在即便Handler是静态弱引用Message.target在Looper执行到它之前一直强引用HandlerHandler又弱引用Activity那Activity理论上可以被回收但Message回调执行时WeakReference.get()返回null代码要做判空。内存泄漏的典型场景还有很多比如单例持有Context、非静态内部类创建了静态实例、匿名Thread持有外部Activity、监听器未注销等。我建议准备这类问题的时候不只讲原理还要讲工具链Memory Profiler看内存曲线、MAT分析Dominator Tree、LeakCanary在测试阶段自动抓泄漏。特别是MAT分析面试官很可能会让你演示“怎么定位是哪个对象持有了Activity”你要能说出搜索Activity类名查看引用路径找到GC Root这一步完整的操作链路。3.2 卡顿分析与UI渲染2018年Android面试对UI渲染的考察还不像现在这么卷但字节已经会问“掉帧是怎么产生的”了。这道题的核心是垂直同步信号16ms内没完成一帧的绘制就会出现掉帧。你还要能说出Choreographer的调用链Choreographer接收VSync信号 → 回调doFrame → 触发measure/layout/draw → 经过RenderThread同步到GPU。我实际面试时被追过一个很难的问题“布局层级为什么影响性能”当时我第一反应是measure和layout递归遍历但这个回答不够根本。面试官想要的答案是层级越深遍历开销越大而且嵌套LinearLayout会导致多次measureRelativeLayout虽然一次测量两次布局但遇上复杂约束也可能触发多次。正确优化思路是减少层级用ConstraintLayout或者用merge减少嵌套用ViewStub延迟加载不常用的布局。在卡顿优化排障方面我推荐用BlockCanary来抓主线程耗时方法用Systrace看渲染链路。面试的时候讲一个真实案例会很加分我当时说了一个列表页卡顿问题最后定位到是item里用了复杂的XML shape作为背景GPU每帧都要重新栅格化后来改成静态位图加setLayerType就解决了。这种案例比背十个优化理论都有说服力。3.3 AMS、WMS与系统服务协作Framework层在2018年校招里是明显的高区分度题目很多候选人能说出四大组件的用法但被问到Application启动流程就露馅了。字节这一批有一道经典题“冷启动一个App从点击图标到MainActivity显示中间发生了什么”这道题要完整串起Launcher进程 → ActivityManagerService → Zygote fork → ApplicationThread → ActivityThread → H → MainActivity。通俗一点讲这就像你去餐厅吃饭你点击图标跟服务员Launcher说“我要点菜”服务员把单子交给厨房AMS厨房Zygote收到后开始做菜fork新进程菜做好由传菜员ApplicationThread端到你桌上传菜员通过一个小喇叭H Handler喊“上菜了”然后你开始吃Activity生命周期。这个类比我面试时用过面试官当时笑了但追问也跟着来了“AMS和ActivityThread之间是什么通信方式”答案是BinderAMS所在系统进程持有ApplicationThreadProxyApp进程持有ActivityManagerProxy两边通过Binder互相调用。WMS相关的问题倾向于“Window和View的区别”。Window是一个抽象概念负责管理View的添加、删除和事件分发ViewTreeRoot是View和WindowManager之间的桥梁。面试官常常会问“WindowManager.addView之后发生了什么”你要能答出WindowManagerGlobal.addView创建ViewRootImpl然后requestLayout启动绘制流程。这个如果能结合Window的类型——应用Window、子Window、系统Window——和type的层级关系一起讲就会显得很有深度。3.4 网络与图片框架的源码思路2018年移动网络这块OkHttp和Retrofit几乎代替了HttpUrlConnection成为面试标准配置。字节问得最多的是“OkHttp的拦截器链是怎么设计的”。你得能说出五大默认拦截器RetryAndFollowUp、Bridge、Cache、ConnectInterceptor、CallServerInterceptor以及自定义拦截器加在链里的效果。为了讲明白我当时把Dispatcher的线程池模型也一起讲了同步请求直接执行异步请求交给Dispatcher的ExecutorService执行线程池配合Deque双端队列管理任务。Retrofit的考察重心是动态代理和注解解析。面试官很爱问“Retrofit是怎么把接口方法变成请求的”答案是Proxy.newProxyInstance生成接口代理对象方法调用时解析方法注解和参数注解生成ServiceMethod再通过OkHttpCall执行。这里有一个容易忽略的细节Retrofit6.0版本之后把CallAdapter和Converter拆得更细所以你的回答最好从“CallAdapter负责线程切换Converter负责JSON解析”这个角度切入。图片加载方面Glide在那几年已经是事实标准所以校招也会考。核心要准备缓存策略内存缓存用LruCache磁盘缓存用DiskLruCache同时在View层还有ActiveResources维护正在使用的图片。生命周期绑定是Glide最大的亮点它监听Activity/Fragment的onStart和onStop来暂停和恢复请求避免图片加载浪费资源。面试官如果追问“既然有LruCache为什么还要ActiveResources”你要答出“LruCache的LRU算法可能把正在显示的图片挤出缓存ActiveResources专门保护正在使用的图片”这一个点。4. 手写代码与算法实战实录4.1 算法题的出题规律字节2018年校招的算法题放在牛客网在线编程里第三批考察的重点集中在链表、二叉树、动态规划和字符串处理。我的感受是他们不追求偏题怪题而是把经典题换个包装反复出比如“反转链表”会变成“K个一组翻转链表”“二叉树遍历”会变成“之字形打印二叉树”。我统计过当时面经里高频出现的算法题两数之和、三数之和、合并两个有序链表、环形链表检测、二叉树最近公共祖先、全排列、最长上升子序列、字符串转整数。如果你时间紧张优先把这几道刷到闭眼能写。刷的时候一定要在纸上或者白板上写不要用IDE自动补全因为面试手写代码没有提示拼写错了会非常尴尬。在线编程平台还有一个细节有时代码只能跑一部分用例是因为边界条件没处理好比如输入为空、单个节点、数值溢出、负数等。我建议每次提交前先按这个清单自查一遍不要依赖测试用例反馈。另外写的时候把变量名取清楚面试官会看你的代码风格几个无意义的a、b、c会让人觉得你没有工程素养。4.2 手写单例模式与生产者消费者字节面试对设计模式的考察不靠问概念而是直接让你手写。最常见的是“手写一个线程安全的单例”而且面试官会要求你每种写法都分析优缺点。我当时的标准答案是核心三种DCL双重检查锁要注意volatile防止指令重排、静态内部类利用类加载机制天然线程安全、枚举最简洁且防止反射攻击。如果时间允许我还会提一句容器式单例毕竟有些框架里注册式单例也用得很多。生产者消费者模型也是高频手写题。2018年我遇到的是用wait/notify实现后来在别家面试还遇到过用BlockingQueue实现和用Lock/Condition实现。这三个版本最好都准备因为面试官很可能会说“你用ReentrantLock再写一遍”考察你对JUC包的熟练度。写的时候注意while循环判断条件而不是if因为多线程环境下需要重新检查条件notifyAll比notify更安全虽然性能略差。除了这两种我当时还准备了一些Android场景的手写题比如LRUCache、线程池封装、异步任务队列。尤其是LRUCache非常像字节的风格——既考数据结构HashMap 双向链表又考并发安全需要加锁或使用LinkedHashMap的removeEldestEntry。我建议手写一遍LinkedHashMap版本再手写一遍双向链表版本这样能展示你对底层原理的掌握程度。4.3 高频设计模式与自定义View设计模式上字节2018年考过“Builder模式在OkHttp里的应用”“观察者模式在LiveData/EventBus里的应用”“装饰者模式在IO流里的应用”。不要只背定义要能结合源码举例。我当时回答观察者模式时讲了EventBus的注册和事件分发流程又从LiveData的角度聊了生命周期感知面试官明显对这个回答很感兴趣还追问了“LiveData为什么不会内存泄漏”——因为Observer包装成了LifecycleBoundObserver绑定了LifecycleDESTROYED时自动移除。自定义View也是Android面试的必考点。第三批有一道题是“自定义View的测量和布局流程”你需要把onMeasure、onLayout、onDraw的关系讲清楚并且区分View和ViewGroup的测量差异。经典场景是“模仿微信九宫格”要处理Wrap_content、Padding和子View的测量模式。我建议拿出源码级的细节来回答MeasureSpec是一个32位的int高两位是mode低30位是sizeUNSPECIFIED、EXACTLY、AT_MOST三种模式分别对应什么场景。事件分发也是高频考点特别是“点击事件为什么会触发父View的onTouchEvent”。面试官期待的是你从Activity.dispatchTouchEvent开始到ViewGroup.dispatchTouchEvent的拦截逻辑再到View的onTouchEvent最终回到Activity的完整链路。记得要区分DOWN、MOVE、UP三个事件在分发中的区别以及requestDisallowInterceptTouchEvent的作用。这一块如果能结合一个实际项目里的滑动冲突案例来说效果会好很多。5. 现场问答与HR面经验实录5.1 技术面追问的底层逻辑字节的技术面通常有两到三轮每一轮结构都很清晰自我介绍、项目深挖、基础题、算法题、反问环节。我最大的体会是面试官不会按顺序问而是顺着你的回答不断切换分支。比如我聊项目时提到用了RxJava面试官立马打断问“那如果流量飞涨你怎么限流”这种随机切换考察的就是你有没有真正理解自己用的东西。被追问的时候最重要的是别慌。有一个技巧如果问题一时没思路先把自己的分析框架说出来比如“我会先看这个问题的输入和输出然后考虑数据结构和复杂度”面试官通常会给你提示。最忌讳的是沉默十秒钟或者东拉西扯。字节的面试官整体都很专业你答错一部分他们不会直接否定而是继续挖看你能不能自己修正。准备项目深挖时我建议按STAR法则把自己的项目拆一版1分钟版本和5分钟版本。1分钟版本用来开场5分钟版本用来应对追问。每个技术选型都要准备“我为什么不用A而用B”的答案比如“图片加载为什么选Glide而不是Fresco”“网络层为什么不用RxJava封装而单独用Retrofit”。这些取舍的理由才是面试官判断你工程能力的核心证据。5.2 HR面试的考察点与回答思路字节的HR面不是走流程他们手里的评价表会影响offer等级和薪资。2018年那一批HR面高频问题是为什么选择字节跳动你最大的优点和缺点是什么有没有跟同学或者同事发生冲突的经历你未来三到五年的职业规划是什么我踩过的坑是第一次HR面把“缺点”说成了“完美主义对细节要求高”这种答案一听就是套话。后来我学乖了缺点一定是真实的但要有改进方案比如“我在公开演讲方面经验不足容易紧张所以我在学校主动报名参加了几次技术分享现在已经能比较流畅地讲完45分钟”。这样的回答才显得可信也让HR觉得你有自我认知和行动力。谈到offer选择的时候HR可能会问“你还有其他公司的offer吗”我建议如实回答但要强调你评估offer的标准。标准不要只谈薪资可以从技术成长、业务前景、团队氛围三个维度展开这能体现你不是单纯比价而是有明确的职业规划。5.3 踩坑总结与答题节奏复盘整个面试流程我最想提醒大家的是节奏控制。每道题的答案不是越长越好而是逻辑清晰、有钩子、能引导面试官往你熟悉的方向走。我那时候准备了很多关于App启动优化的细节所以每次讲到项目启动优化时会故意留一句“这里涉及冷启动全流程的优化我踩过不少坑”面试官大概率会顺着问这比我被动等题要舒服太多。时间分配上自我介绍控制在两分钟到三分钟不念简历上的罗列项而是讲一个完整的技术故事。项目深挖一般会占用十五分钟到二十分钟剩下大部分时间给基础题和算法题。如果你发现某个基础题答得不好别纠结赶紧调整好状态进入下一题因为面试官根本不会因为一道题定生死。关于“如果遇到不会的问题怎么办”我的经验是分两层处理。第一层如果是完全陌生的概念就诚实说“这个知识点我了解不多但根据我的理解可能是……”面试官会判断你的推导是否合理。第二层如果是自己项目里的技术点但忘了细节就不太合适了所以项目里提到的每个技术都要复习到不要为了好看堆名词。最后再分享一个小技巧面试前把手机录音打开回来复盘你会发现很多当时没察觉的问题——比如口头禅太多、某些技术点讲得含混、算法题讲解时逻辑跳跃。我第一次听录音时非常不好意思但正是这些复盘让第二轮面试明显顺畅了很多。字节2018批次的考察内容虽已过去几年但底层考察逻辑依然很值得参考扎实的基础、对源码的理解、真实项目的反思、流畅的表达你把这四样练到位无论哪一年的校招都能稳住阵脚。
返回列表