前言
从公开简历以来也面试了4家,猫眼是第四家,这里也是通过了技术二面,再等三面和hr,首先先说点个人的面试感受吧,谈不上经验,因为面的次数比较少。
- 场景化问题增多
很多技术点不再是单纯的原理或者api层面的东西,很多都是结合一定的应用场景让你来说实现方案,甚至部分代码细节,举个例子大概就类似问Activity的生命周期,不在是简单的说出几个回调而是结合app日常操作的场景来说。当然这个例子比较常见,但就是类似这种思路的。
- 多数问题是根据你的简历来问的
比如你项目中写了性能优化很大概率会让你结合你的项目问这个问题,你在中间充当什么角色,优化了那些地方,然后取得什么样的成果,然后再扩展问
- 有些问题是在你回答前一个问题的答案中引出的
什么意思呢?说白了就是自己给自己挖的坑,有些是可以避免的,有些只能默默承受,举个我真实碰到的例子吧,咱谈Retrofit的时候,网络框架的封装这方面,提到了返回数据结构一般都是
int code;
String msg;
T data{
}
这种结构的,所这里就引出了泛型知识点
- 懂原理也要懂实现,具体到代码
打个比方Binder 你不但要了解原理,还要了解实现aidl messager等,甚至具体到代码里如何获取代理对象,asInterface传递什么参数这种。
感受就先谈这么多吧,接下来就说一下猫眼面试问到的问题,啰嗦一下很多问题其实和你的简历中的技能和项目经验有关,所以这里仅仅是罗列出来仅供参考,以下问题顺序并不是面试时的发生顺序,因为有些真的记不清了,但是我尽量还原当时的顺序。
一面
- 手写双重校验锁单例(可能看我带着笔并且前台小姐姐也提供了纸);
面试的时候我一般都带着纸和笔,这样方便整理思路,同时也可以记录一下面试官说的问题中的关键字
- 因为上题单例中有volatile 和 synchronized 所以引发了这个Java问题中场景的锁问题,这里最好说到汇编指令上;
- synchronized又引发Lock锁问题,进行对比常见的面试题synchronized和Reentrantlock的区别;
Java锁,线程安全等问题是一定会被问到的, 这方面一定要准备。
- 线程池,构造参数详解,API中提供的4个线程池实现类,区别,主要是拒绝策略和任务队列上,项目中使用过哪些;
- OkHttp源码,拦截器重试机制的实现
- Retrofit如何将接口变成OkHttp请求中真正需要的Request请求体的(Java动态代理 注解 反射)
- Retrofit的接口上面的注解是运行时注解还是编译期注解;
- RxJava操作符说几个,zip操作符;
- 注册后获取Token成功后再进行登录,不成功不登录,用RxJava的那个操作符;
关于这个问题我有一些要说,就是实际上上面两个问题都是api层面上的,也就是RxJava使用上的,可能项目中长时间不用,或者学过后忘记了,我就是这样,但是我们需要理解面试官想要的答案,其实这里无非就是想用一种事件失败后可以中断事件流的操作符,所以我就说选用具有这个特征的操作符,但是具体是什么操作符,我真的没有印象了,面试官也不会为难你,起码你get到了他的意图,其实这道题就算你答对了大部分了!
- Java泛型的理解,类型擦除啊,谁干的这事…
- Rxjava线程调度的原理…
这里也是完全不知道,Retrofit和Rxjava准备的真的很一般,虽然自己git上有自己封装的基于Retrofit+Rxjava的网络请求框架,甚至从RxJava1升级过RxJava2 ,但是还是不记得了,好久没用了,只能说Handler了,因为最起码它确实是线程间通信的方式之一,这里也是希望通过个人的经历来告诉大家,学的东西一定要用到项目中,反复研究才能真正的融会贯通,不然学了也是浪费时间。切记切记
- Handler通信机制(回答过程中又被深入提问)
这里由于说到C++层,提到了底层通信方式管道,也就提到了管道的读端文件描述符和写端文件描述符,以及休眠等,所以给自己挖了个坑,问了下这个休眠的唤醒机制是什么,这里完全不记得了,只记得有看过。其实即使我说出这个机制我也不太明白原理,所以我就坦诚的跟面试官说不知道,但是我确定肯定有这种机制,这样从原理层上给予肯定,最起码比完全说不知道要好一些。
附答案:Looper中的睡眠等待与唤醒机制C++类Looper中的睡眠和唤醒机制是通过pollOnce和wake函数提供的,它们又是利用操作系统(Linux内核)的epoll机制来完成的,具体想了解epoll这里就不科普了。
- 上边问题提到Looper,这里就继续问Looper在Android的ActivityThread中也是调用Looper.loop开启循环,这里为什么这个死循环不会卡死;
这也是一个比较经典的面试问题了,建议都准备一下,答案可以去知乎上去找,这里简单说一下就是Android是事件驱动型的,这个Looper并不是简单的循环,CPU有休眠,上面问题说到过,然后有等待唤醒,一个App创建的时候除了主线程,至少会有两个Binder线程,对外是通过这个Binder线程来交流的
- 由于上面答案里提到了Binder这里又追问了Binder原理,然后aidl等,Binder原理这一块面试高级必须准备,了解的越详细越好,不多说;
还是啰嗦一下 有一个关于Binder优势的问题就是 为什么Binder是一次内存拷贝 这个可以看一下,还有就是Intent的传递数据大小限制也和Binder的缓冲池有关。
- 项目经验中写了些优化,谈了启动优化,布局优化,网络优化,然后被追问了Bitmap优化,四种色彩的存储模式(ARGB8888这些)下内存占用。
- Glide是如何监听Activity生命周期的;
- 数据结构ArrayList、LinkedList和HashMap,基本上你能想到的都要说,内存是否连续啊,HashMap扩容1.7和1.8区别啊什么的。
- HashMap重写hashCode问题,用自己写的引用类型做key需要注意哪些,需要说hashCode和equals问题,
- LRU;
- 最后手写一个判断是不是回文数的算法;
一面大致就记得这么些了,哦还有问了下是否了解JNI ,我直接说C/C++一般就没问了,10分钟写算法然后这中间换了二面的面试官。
二面
首先是看了下一面中的算法,我这里只写了最简单的反转之后O(N)时间复杂度的对比,然后被问到有没有更优的,时间复杂O(logN)的这种…我要是知道肯定一上来就写最优的了,果断放弃,也不给他引导我的机会…因为算法真的是噩梦!
- 静态内部类问题,能否调用外部类的非静态私有属性,面试官甚至手写了代码问你编译能否通过;
public class OuterClass {
private int a = 5;
static class InnerClass {
public void methodA() {
System.out.print(a);
}
}
}
升级版
public class OuterClass {
public static void main(String[] args) {
InnerClass in = new OuterClass.InnerClass();
in.methodB();
}
private int a = 5;
static class InnerClass {
WeakReference<OuterClass> wr = new WeakReference<OuterClass>(new OuterClass());
public void methodB() {
int b = wr.get().a;
System.out.print(b);
}
}
}
以上问题不但要你回答正确,还要问你为什么可以为什么不可以
- 接口里面可以有成员变量吗?为什么不可以有具体方法实现,抽象类可以有方法实现吗?
这个问题真的是特别的好,只有真正了解接口和抽象类才能回答的比较完美,建议大家去查一下,这种我们平时经常使用,觉得理所当然的东西,很多时候恰恰就是我们的知识盲区,真的可以说是灯下黑…
- Java类加载机制,从加载到卸载,以及3个加载器和双亲委派模型;
- Java枚举,考察一下使用,自定义枚举,以及默认值问题,要求手写;
自定义枚举开发中我是用过的,但是也只是那么几次,上次大概是两年前了,所以根本就想不太起来了,然后也是没写太对,只能跟面试官说Android中枚举占内存大这个弊端,然后说基本都是用静态常量来代替了,比较尴尬的甩锅哈哈。
- Java集合框架Collection Map…然后突然问迭代器Iterable属于哪个… 当时有点懵,还好悬崖勒马…
- 常用的数据结构,然后又说了一遍HashMap…然后问了还用过哪些数据结构等等,提到了ConcurrentHashMap,如何加锁如何实现线程安全的,这类数据结构问题必须准备HashMap更是重中之重。
- 然后看到了我上场面试手写的单例,然后又问了一遍锁的问题;
着重说了下volatile,包括可见性,有序性问题,立即写回主内存,使其他工作线程无效的问题,
以及synchronized和Lock锁的区别,问了可重入问题,公平锁等,再次说一遍synchronized1.6后的优化;
- 其他单例,手写静态内部类单例。
- 线程池,又问了一遍 基本和一面一样,所以可以看出来这个问题被问到的概率…
- OkHttp拦截链 5个拦截器的作用,重试机制如何实现的,又问了一遍
- List item项目中安全问题,混淆加固,问加固有没有自己搞过还是第三方 ,这里面试官也是吐槽自己搞需要团队做很多事情,算是放松环节问题吧;
- 因为项目中写了HTTP和HTTPS 所以问了这个问题,那个更快,HTTPS都做了什么,项目中做了哪些?
- 响应码 2XX 3XX 4XX 5XX; 提到206的断点续传的时候问了还需要哪些请求头…也是给自己挖了坑;
- Retrofit中BaseUrl的问题,比如项目中有些第三方例如广告这些域名并不是我们自己的,怎么应对这种多BaseUrl问题
这里在前一家面试的时候有问道过,我自己早期也研究过,也看过相关博客,大致记得就是直接在Retrofit注解中写全域名,或者请求头中加东西,利用标志来更改URL地址,再Low一点的就是创建多个OkHttpClient对象,然后面试官问我还有什么可以框架本身支持的这种,我就想到了重定向,以及拦截器练这种方式,算是过关了
- Activity启动模式,singleinstance重点问了下,然后问了下是否一定会开辟新的activity栈
- 场景问题,A activity singleinstance启动模式,BC都是Standard 然后A 启动B B启动C ,HOME键,History列表中找回应用,然后两次Back键,问当前显示在哪个页面…
- 广播 应用内私有广播,然后因为答案中提到了Intent,所以又问了Intent隐式启动问题,然后自己给自己挖坑提到了组件化,引出了路由实现…这里也是打自己脸 ,让你欠…
- 布局优化,然后又被问到了新的版本下有哪些布局
除了传统的LinearLayout RelativeLayout,我知道的我也不会发音,所以只能说有两个C开头的 一个是拖拽的那种,还有MD风格下的,还有一些和toolBar哪些相关的,面试官说理解了我的意思 ,就放过我了…哈哈
- 过渡绘制,那种颜色代表什么意思,还挖坑问我有没有紫色…
这里加一个小插曲,基本聊到这里氛围就很好了,面试官还自言自语思考Java有哪些没问的问题,然后问我在一旁提醒,JVM 垃圾回收这些,当然这些是我比较有信心的问题,我才不会给自己挖这么明显的坑呢 哈哈~~
- 注解@Retention的取值,这里只记得有3个实际上还是一面中谈到的,只说出了两个的名字,剩下一个说想不起来了,不过好在知道是3个也没难为我;
- Java序列化
因为这里如果干说Java序列化估计我也说不了两句,所以我把Android的序列化拿出来一起说了,说了下性能上有区别的原因,也说了Android序列化的编写的复杂,当然也谈了插件的便捷模板生成,说了Java序列化注意的问题ID的那个
- 面试官手写代码问分派的问题
TestOne
public abstract class TestOne {
public abstract void method1();
public void method2(){
System.out.print("AAA");
}
}
TestTwo
public class TestTwo extends TestOne{
@Override
public void method1() {
System.out.print("BBB");
}
@Override
public void method2(){
System.out.print("CCC");
}
}
Test
public class Test {
public static void main(String[] args) {
TestOne test = new TestTwo();
test.method2();
}
这里也是但是知道问的问题是分派相关的,但是正好弄反了,看来理解的还是不够透彻,动态分派的重写,静态分派的重载,然后面试明知道我回答错了(我当时回答的是输出AAA),然后问我怎么改能输出CCC… 然后还问我原因,我还说是分派的事…
- ABCD4个standard启动模式中都有处理主线程消息的Handler,都能接收到Message what 1000的消息,ABCD顺序启动, F D 中 Message.send了一个what 1000的消息, 只有C收到了,问什么场景下会出现这种情况…
也是生无可恋了,我只能试探性的说一个我认为的可能性,比如Handler对于消息出来的优先级 msg callback 自身callback以及我们经常重写的handler方法的回调接受顺序上来说这种,他没放过我,问还有吗…
到此好像二面就结束了,然后我们过程中聊的也很愉快,基本上我全程保持微笑,然后遇到自己给自己挖坑而回答不上的时候,我也会自嘲一下,然后问面试官我是不是给自己挖坑了,面试官也很友善,只是强调探讨,大家都是Android开发什么的,也怕我多想,然后这样聊着基本上大家都很放松,过程也很愉快,总之你要给面试官留下好相处的印象,然后拉近你与他的关系,就比如同为开发这个身份认同感,对于某些觉得不合理的东西共同吐槽,这样可以从面试这种对立关系,变成一种同仇敌忾的关系,这也算是面试的一个小技巧吧。
二面的面试官出去和一面的沟通了一下,然后回来和我说我符合他们这边的要求,然后说因为校招,他们的负责人去上海了,还需要和负责人沟通一下,今天就先到这里,然后说如果HR面的话可能还要过来一趟,然后我问了三面还有技术问题吗,他说应该不会有了,但是负责人技术出身也说不好…但是问的话应该是一些大的方向上比较高屋建瓴的东西了,然后就是一些有什么问题要问他的这种常规问题,这里就不表了。
以上就是我猫眼面试的全过程了,希望对大家有帮助,也纪录下来 通过这次面试也是一个查缺补漏的过程,也知道了自己还要学习的方向