怎么说呢,这次面试能过真的挺开心的。
一面(1 月 13 日,68 min)
提问
- 自我介绍
- 简单讲讲你项目的整个设计过程
- 你提到项目中用的是 MVVM 架构,讲讲你对 MVVM 的认识?
- MVVM 的优点有什么呢?
- MVP 中 Model、View 和 Presenter 的持有关系是怎么样的?
- MVVM 中的持有关系呢?
- MVVM 中各个层在 Android 开发中的对应关系?
- 你的 MVVM 用到了 Jetpack 里的 ViewModel,那么它是如何保持数据的呢?
- ViewModel 是怎么做到在 Activity 销毁重建新实例之后还能保持不变的呢?
- 你有提到说用的 Kotlin,那讲讲 Kotlin 用起来相比 Java 的好处?
- 如果用 Kotlin 去调用一个具有返回值的 Java 函数,那么这个返回值是可空的还是非空的呢?
- Kotlin 中的可见性和 Java 是不一样的,分别讲讲?
- 你说你用到了协程,讲讲你对于协程的认识?
- 你提到了协程分为有栈和无栈两种。它们的区别是?
- 这个“栈”里都保存了什么信息?
- Kotlin 的协程是无栈的,那这些信息是怎么保存的?
- 协程该怎么取消呢?
- 取消协程之后,里面的工作会立刻停止吗?
- 不会的话,该怎么停止呢?
- 调用了
cancel()
之后协程的状态变化? - 如果子协程中没有通过判断协程状态来决定是否终止工作,那么取消父协程之后会是怎样的?
- 协程会不会和线程一样有共享变量冲突的问题呢?
- Kotlin 中有一个
inline
关键字,讲讲你的了解?- 除了通过内联函数减少函数调用的开销,还有什么用途吗?
- 如果现在有一个高阶函数被
inline
修饰,我不想让它的参数被内联,该怎么办呢?刚开始的时候这个问题没太听懂,所以就答了不知道。一面结束之后翻书才看到noinline
关键字。
- Kotlin 是可以跨平台编译的,讲讲你的了解?
- 你刚才提到的编译到“原生平台”,指的是什么?
- 现在如果让你用 Kotlin 写一个跨平台的项目,你该怎么做?
- 浏览器里从输入一个网址,到最终看见网页,发生了什么?
- HTTP 是应用层协议,讲讲是如何建立的?
- 你说底层是 TCP,那讲讲 TCP 的三次握手?
- 如果现在要使用 HTTPS,连接的建立会发生什么变化呢?
- 客户端是如何根据 IP 地址找到服务器对应的主机的呢?
- HTTP 是应用层协议,讲讲是如何建立的?
算法
题目开始理解错了。最后这个题没完全做出来,面试官让我讲了下思路。
反问
- 部门业务?
- 面试评价?
- 我还有什么需要学习的地方吗?
- 面试官反问:这次面试只是为了实习还是说有转正想法的?
- 部门业务开发语言?
- 多久能收到结果通知?
二面(1 月 14 日,60 min)
一面结束后等了十几分钟,HR 通知第二天二面。
提问
- 自我介绍
- 项目介绍。用到了什么技术栈?
- ViewModel 的作用是什么?
- 你在 Fragment 之间传递数据的时候是怎么做的?
- 为什么不用一个全局的静态变量呢?
- 你在 Fragment 之间传递数据的时候是怎么做的?
- 你有用 LiveData 自己封装了一个事件总线,讲一讲实现?
- 对 Retrofit 的基本结构或者源代码了解吗?
- Retrofit 有一个动态代理的过程,有听说过吗?
- ViewModel 的作用是什么?
- Kotlin 和 Java 都是在做这个 Android 项目中学习的吗?
- 在 Kotlin 和 Java 中,实例的初始化顺序(成员变量、静态变量、构造函数等)分别是怎样的?
- Kotlin 的作用域函数(
let
、apply
等)有了解过吗?你是怎么理解的?具体来说它们有些是带 Receiver 的、有些是带参数的,你在使用过程中是怎么选择的呢? - OOP 中的设计模式有了解过吗?
- Java 中的单例模式分为那些呢?
- Kotlin 中的
object
相当于 Java 中的哪一种单例模式?- 饿汉式是怎么做到线程安全的?
- 类加载器又是在什么时候去加载这个类呢?
- 解释一下饿汉式中存在的性能问题?
- 在 Kotlin 中如何实现懒汉式单例?
- 饿汉式是怎么做到线程安全的?
- Java 中 DCL 单例模式中双重校验的意义?
- Jetpack 的其他组件有了解过吗?
- Room 使用的基本流程了解吗?
- SQLite 平常你是怎么用的呢?
- Room 使用的基本流程了解吗?
算法
反问
- 部门业务?
- 是纯原生开发吗?
- 面试评价?
- 还有什么需要学习的?
- 面试官反问:对工作地点有要求吗?
- 多久能收到结果通知?
三面(1 月 15 日,40 min)
二面结束之后等了大概一个小时多,HR 通知第二天三面。
提问
- 自我介绍 & 项目介绍
- 项目是你自己在做吗?
- 介绍一下项目的模块和功能?
- 项目中用到的数据都是怎么获取到的?
- 学校的系统里没有什么安全措施吗?
- 你这个项目有这么多人在用,是怎么推广的呢?
- 后续有和学校交流让你这个项目变成官方 App 吗?
- 项目中有什么技术难点吗?
- 有了解过 Retrofit 是如何简化网络请求的吗?
- 解释一下动态代理?
- Retrofit 会结合一些注解进行使用,对注解有什么了解吗?
- APT 有听说吗?是做什么用的呢?自己有上手用过吗?
- AOP 的概念有了解吗?
- Jetpack 的 AAC 中是如何做到生命周期的分发的呢?
- Jetpack 组件还了解哪些呢?
- Compose 有了解过吗?最开始没想起来,后来面试官提到 Flutter 才想起来是新出的一个声明式 UI 框架。
- Flutter 有了解过吗?
synchronized
关键字修饰静态方法和非静态方法的区别?- 一个类中有一个静态方法 A 和非静态方法 B,都被
synchronized
修饰。两个线程分别去调用同一个实例的方法 A 和方法 B,会产生竞争吗?
- 一个类中有一个静态方法 A 和非静态方法 B,都被
volatile
关键字的作用?- 解释一下“立即对所有线程可见”和“禁止指令重排”?
- Java 中的四种引用类型有了解过吗?
- 分别有什么区别呢?
- GC 机制有了解过吗,比如算法之类的?
- 一个 View 要渲染出来,需要经过哪几个步骤呢?
- 这些步骤各自对应了一个回调方法,对 View 的什么操作会触发对这些回调方法的调用呢?或者说,不同的操作会触发不同的调用吗,比如有的调用,有的不调用?
- 除了在 Activity 创建的时候,后续对 View 的哪些操作会触发这些回调方法呢?(这里确实没复习到,现场通过 TextView 举例结合了这三个阶段的回调方法名开始猜)
- 如果说 TextView 大小固定呢?
- 除了在 Activity 创建的时候,后续对 View 的哪些操作会触发这些回调方法呢?(这里确实没复习到,现场通过 TextView 举例结合了这三个阶段的回调方法名开始猜)
- 这些步骤各自对应了一个回调方法,对 View 的什么操作会触发对这些回调方法的调用呢?或者说,不同的操作会触发不同的调用吗,比如有的调用,有的不调用?
- 除了绘制,View 还有一些事件的传递机制,有了解吗?
- 过程中的几个关键过程回调是哪几个呢?
- 有听说过“过度绘制”吗?这个没答上来,然后面试官很耐心地解释了这个概念,实际上就是两个 View 叠在一起,下层被上层挡住的部分是看不见的,但还是会进行绘制。
编程 & 提问
给一个 List<String>
,遍历并删除指定元素(比如 abc
),写出代码(大概就是自己实现 List#removeAll()
)。
三面不出算法题是我没想到的。这个题也挺简单,就是利用迭代器遍历然后删除就好。
因为对迭代器不是特别熟悉,所以开始写的时候并没有单独用变量
it
把迭代器存下来,而是在每个要用迭代器的地方都获取了一次,然后跑起来报错了。后来意识到之后就改了。
List<String> list = new ArrayList<>(); list.add("abc"); list.add("abc"); list.add("abc"); list.add("123"); list.add("abc"); Iterator it = list.iterator(); while (it.hasNext()) { if (it.next().equals("abc")) { it.remove(); } }
- 你刚才为什么会出错呢?然后面试官从代码规范和迭代器的使用两个角度讲了一下为什么应该把迭代器提前存到变量里面,还提到了
WeakReference
相关的东西。 - 能不能把
it.remove()
换成list#remove("abc")
进行删除操作呢?- 会报什么错呢?一紧张没敢确定说是 Fast-fail,面试官允许我先运行了一下再说。
- 不用迭代器实现的话需要考虑什么呢?为什么你会首先想到使用迭代器呢?
- 为什么不能在下标遍历过程中进行插入和删除呢?
- 能不能在
for-each
遍历中进行删除呢?
反问
- 实习生会有人带吗?
- 面试表现?
- 学习建议?
HR 面(1 月 15 日,27 min)
三面结束后一个多小时左右,收到了晚上继续 HR 面的通知。
提问
- 评价一下自己前三面的表现?
- 如果重来一次的话,对于答不上来的问题你会怎么办?
- 介绍一下你的项目?
- 项目中遇到瓶颈是怎么解决的?
- 你觉得你这个项目对你有什么提升?
- 你觉得自己有什么优点和缺点?
- 你打算如何去改进自己的缺点呢?
- 你平常放松自己会通过什么方式呢?
- 你觉得大学中最紧张的时间段是什么时候呢?
- 你是打算实习然后转正吗?
- 为什么现在不想考虑转正呢?
- 那后续的话除了字节你还打算去哪些公司呢?
- 你是为什么打算去这些公司呢?
- 你平常会怎么安排自己一天的时间呢?
- 入职之后你打算怎么平衡实习和课业学习呢?
反问
- 核酸检测
- 薪资
总结
这次实习面试走的学长内推,12 月 31 号投的简历,1 月 6 号收到 HR 电话。隔这么长时间还是挺害怕的,以为简历都被筛掉了。因为是在期末考试周,就把面试约到了再一周以后。最开始 HR 是打算直接把三面安排到一天,但是考虑到我的准备程度还是没太敢,商量了下先一面。1 月 15 号面试结束,最后 1 月 19 号 OC。
字节的面试体验还是相当不错的。过程中面试官会很耐心地听你讲,对于答不太上来的问题,给出大体思路也是可以的。回答不上来的东西,面试官也会在面试过程中跟你简单介绍一下。大概这就是为什么最开始 HR 和邮件里都有说“不会的题也鼓励和面试官交流想法”吧。反问环节请面试官对面试过程进行评价,以及对个人能力提出一些建议的时候,面试官还是很乐意的,也很能抓住我的不足(废话不然为啥人家能是面试官呢)。
关于面试中为什么被问到了很多 Kotlin 以及 MVVM 相关的东西,这个是因为我简历上写了之前在学校做过的一个项目。所以基本上三场技术面中相当多部分的提问是围绕着项目进行的。
在开始面试之后,HR 全程跟进的速度非常快。每场面试结束之后 HR 会询问一下面试感受,还会鼓励我复盘一下。给我感觉就是整个过程是有人在引导着我,而不是说我一个人闷头走。这一点是非常棒的。
一些小想法
收到 OC 时候的感觉,和 2012 年小升初收到录取通知的时候是类似的。
为什么这么说呢?小升初的时候,在截止报名的前一天,我突然跟家里说,我不想去 A 中学了,我还是想去 B 中学。B 中学在市里的排名比 A 中学要高,相应地进入的难度也更大。而如果我选择 A 中学的话三年的学费是可以全免并且进重点班的,选择 B 中学就不得不参加考试,根据成绩决定进哪个班。
父母当时对我突然的改变感到挺惊讶的,但最后他们还是尊重了我的想法。由于我当时上的奥数班并没有安排我参加 B 中学的内部考试,也因此我就只能走市里的小升初考试(时间统一,各校自主命题)这条路。因为那年是市里第一次实行小升初考试,所以说并没有特别有用的以往的资料作为参考,每天晚上只能是闷头刷所谓“真卷”。
出成绩那天其实还是挺紧张的,万一没过的话就只能上户籍所在地的对口中学了,而一般对口中学都是很垃圾的。查分时间到的时候,我赶紧敲了个人信息,回车之后首先映入眼帘的是“已录取”三个字。那一瞬间整个人都解脱了——有学上了。而后仔细一看,发现比录取分数线高了 5.5 分,还是挺悬的。
回到这次面试,为什么说 OC 时候的感觉更像是小升初而不是高考呢,因为这两次都有一种“背水一战”的感觉。11 月份的时候尝试面了一次腾讯,结果以一面挂掉告终。之后直到年底最后一天简历投出去之间,一边怀疑着自己的能力到底是个什么样,一边补着 Android 开发的一些知识。
说实话这次投字节也是挺冒险的。因为马上大三上学期要结束了,所以工作室的姐大就催着几个还没找到实习的赶紧投了。本来是应该先投一些小厂练手的,结果被 luy 和 sanzenin 一怂恿,心一狠找了另一个同学 canqz 认识的一个学长内推了字节。31 号投出去的简历,直到 6 号才收到面试通知。中间等起来真的非常辛苦,因为不知道什么时候会约上面试,所以我不得不在准备面试和复习期末考试之间反复横跳。
5 号的时候 luy 完成了他的二面,然后 sanzenin 在准备着他的一面。这个时候还没有收到消息的我心态又突然炸掉了,这次炸得还比较狠,没控制住情绪差点跟 luy 吵了一架。后来某天跟他再次说起这个事情的时候我居然还没意识到当时我的不对,现在想来确实挺对不起的。
然后考虑到期末考试真的快顶不住了,我决定先放一放面试准备,专心备考。6 号收到 HR 电话的时候并约到考试后一周开始面试的时候,整个人松了一口气,并行的事情可以串行了。最后期末考试的成绩还算看得过去,然而当时我的想法是就算四科全挂我也要换面试通过。
9 号回到家之后摸了一天鱼,真正开始准备已经到了 10 号了。实际上这会儿再精心准备已经来不及了,我就分了三天,一天算法、一天 Android 和一天基础知识。算法一直是我的心头大患,直到面试的时候我还是不能很快地给出一个不错的解答,好在面试官没有在算法上为难我。想吐槽的一点是,面试前突击一天的题目里没有遇到一个原题,反而是很久之前的题被出了出来。当然在牛客上字节客户端面经里经常出现的 36 进制加法和 64 马问题并没有出现在我的面试里。
而 Android 方面,说实话那会儿我的知识储备只是比 11 月份多了稍微一些。简单来说就是大概知道一些浅层的东西,深层次的原理或者是源代码并没有仔细研究过。加上牛客面经里涉及到的东西太多太杂了,我就决定首先梳理清楚电表,列出来所有可能会被问到的问题然后逐个去背(对,真的是背)。其他方面的话就是跟着之前看到的一份不错的 Android 面试复习指南准备。不过最后被问到的问题绝大多数都是和电表相关,或者说是由它引出来的。而其他一些问题则刚好是我看过的。不得不说,真的非常走运了。
13~15 号连着三天完成了全部的三场技术面和一场 HR 面。每一面结束之后的当天我都能收到下一次面试的通知,这个是比较出乎我的意料的。但实际上每次结束之后我都非常害怕,一直在回忆自己说了“不了解”“没用过”,然后担心会不会因为这些挂掉。
还有就是,luy 和 sanzenin 都是在学校完成的一二面(sanzenin 的三面也是在学校完成的),面试之前有人唠嗑缓解紧张。我在家的时候就只能在群里打字。另外我开始一面的时候,luy 已经 OC 了,sanzenin 也完成了三面。这个从某种角度来说也是我压力的一个来源吧。平常在工作室人模狗样的,面试挂了的话我怕我真顶不住。
15 号面完之后算是放松了一半,内推我的学长当时表示 HR 面只要不搞幺蛾子就没什么问题。18 号和 19 号连着两天上午我都在问 HR 进度,然而 HR 也并不能控制这个进度,没办法就只能干等。下午配完眼镜,刚开门回到家的时候收到了 HR 的 OC。和八年前一样,一瞬间解脱了。
我自认为我是个比较爱“钻牛角尖”的人,有些时候一旦认定了一个目标的话就不太愿意放手,直到最后结果出来(当然高考是个意外)。我也不知道这种性格到底好不好,不过目前看来似乎并没有带给我什么坏处。学校里我认识的准备 Android 方向的同学几乎没有,在这个过程中基本只能靠自己。现在,我可以对半年前的我提出的问题做出一个回答了:“你学的东西有用,而且派上了大用场。”
说了这么多我自己,再说说周围的人吧。这一路上真的是受到了各种各样人的帮助,先是 luy,再是工作室的小伙伴们。进入工作室之后我才知道面试该准备些什么,以及如何准备。除了 luy 和 sanzenin 之外,工作室里尤其要感谢姐大和学长 crabxmz。虽然姐大不是技术岗,但是在修改简历方面给了很多相当有用的建议。学长则是一直鼓励我们几个大三同学往前冲。还有通过 canqz 和他的学长,我才能获得这次面试机会。这学期让我越来越感觉到,认识很多朋友、很多好朋友真的是非常重要和有帮助的一件事。本当に、ありがとう。
2021 年的新年愿望就是拿到实习 Offer,现在实现了。似乎这是这么多年我实现的第一个新年愿望。接下来一段时间的社畜生活还是相当期待的,自己选择的路,自己要走下去。
学长tql 优秀学长我的榜样
啊是今年暑假 可恶的输入法!!!
芜湖~希望明天暑假能和学长一起工作~