“我是培训 + 外包出来的,确实有被甲方嫌弃过“,开发八年后面试字节资深工程师定薪60W成功逆袭!

对于这个问题,某互联网公司技术总监曾经说过:外界的确存在一些公司认为培训班出来的程序员是“速成品”,然后卡简历的情况。“其实不是说培训机构出来的程序员表现都不行,只是表现不好的程序员可能都有过培训经历,行业里一传十、十传百就会认为培训机构出来的程序员都不行。”

培训 + 外包拿下字节的历程

我认识的一位培训+外包出身的程序员,目前开发8年多,最近去面试了今日头条的移动Android资深工程师,定薪年薪60W!果然功夫还是不负有心人啊,只要坚持努力总会有结果的!

接下来分享一下他的Android资深工程师面试经历:

今日头条的面试主要分为三轮,首先是基础面试,基本面试10个题左右。

第一面是北京的开发进行视频面试,有理论和编程题组成。用的是在线编程工具,如下图;

第一面

1,请编程实现单例模式,懒汉和饱汉写法

//饱汉写法

public static Singleton getInstance() {

if (singleton == null) {

synchronized (Singleton.class) {

if (singleton == null) {

singleton = new Singleton();

}

}

}

return singleton;

}

//懒汉写法

private static final Singleton1 single = new Singleton1();

//静态工厂方法

public static Singleton1 getInstance() {

return single;

}

2,请编程实现Java的生产者-消费者模型

看到这个有点懵逼,要是大学毕业的时候写这个肯定没问题,这都工作多年,这也只能按照自己的思路写了。我使用synchronized锁以及wait notify实现一个比较简单的。这里就不作展示了

3,HashMap的内部结构? 内部原理?

关于HashMap的问题,不再详述,这方面的资料也挺多,不过需要注意的是Java1.7和1.8版本HashMap内部结构的区别。

4,请简述Android事件传递机制, ACTION_CANCEL事件何时触发?

第一个问题不做解释。。

关于ACTION_CANCEL何时被触发,系统文档有这么一种使用场景:

在设计设置页面的滑动开关时,如果不监听ACTION_CANCEL,在滑动到中间时,如果你手指上下移动,就是移动到开关控件之外,则此时会触发ACTION_CANCEL,而不是ACTION_UP,造成开关的按钮停顿在中间位置。

意思是当滑动的时候就会触发,不知道大家搞没搞过微信的长按录音,有一种状态是“松开手指,取消发送”,这时候就会触发ACTION_CANCEL。>

5,Android的进程间通信,Liunx操作系统的进程间通信。

关于这个问题也是被问的很多,不多啰嗦了解释了。

6,JVM虚拟机内存结构,以及它们的作用。

这个问题也比较基础,JVM的内存结构如下图所示。

7,简述Android的View绘制流程,Android的wrap_content是如何计算的。

8,有一个整形数组,包含正数和负数,然后要求把数组内的所有负数移至正数的左边,且保证相对位置不变,要求时间复杂度为O(n), 空间复杂度为O(1)。例如,{10, -2, 5, 8, -4, 2, -3, 7, 12, -88, -23, 35}变化后是{-2, -4,-3, -88, -23,5, 8 ,10, 2, 7, 12, 35}。

要实现上面的效果有两种方式:

第一种:两个变量,一个用来记录当前的遍历点,一个用来记录最左边的负数在数组中的索引值。然后遍历整个数组,遇到负数将其与负数后面的数进行交换,遍历结束,即可实现负数在左,正数在右。

第二种:两个变量记录左右节点,两边分别开始遍历。左边的节点遇到负值继续前进,遇到正值停止。右边的节点正好相反。然后将左右节点的只进行交换,然后再开始遍历直至左右节点相遇。这种方式的时间复杂度是O(n).空间复杂度为O(1)

//方法1

public void setParted(int[] a){

int temp=0;

int border=-1;

for(int i=0;i<a.length;i++){

if(a[i]<0){

temp=a[i];

a[i]=a[border+1];

a[border+1]=temp;

border++;

}

}

for(int j=0;j<a.length;j++){

System.out.println(a[j]);

}

}

//方法2

public void setParted1(int[] a,int left,int right){

if(left>=right||lefta.length||right0){

for(int i=0;i<a.length;i++){

System.out.println(a[i]);

}

return ;

}

while(a[left]<0){

left++;

}

while(a[right]>=0){

right–;

}

if(left>=right||lefta.length||right0){

for(int i=0;i<a.length;i++){

System.out.println(a[i]);

}

return;

}

swap(a,left,right);

left++;

right–;

setParted1(a,left,right);

}

private void swap(int a[],int left,int right){

int temp=0;

temp=a[left];

a[left]=a[right];

a[right]=temp;

}

public static void main(String[] args) {

int a[]={1,2,-1,-5,-6,7,-7,-10};

new PartTest().setParted1(a,0,a.length-1);

}

显然,第二种实现的难点比较高,不过只要此种满足条件。

第二面

1,bundle的数据结构,如何存储,既然有了Intent.putExtra,为啥还要用bundle。

bundle的内部结构其实是Map,传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组,也可以是对象或对象数组。当Bundle传递的是对象或对象数组时,必须实现Serializable 或Parcelable接口。

2,android的IPC通信方式,是否使用过

这方面的资料比较多,也不方便阐述

3,Android的多点触控如何传递 核心类

4,asynctask的原理 AsyncTask是对Thread和Handler的组合包装。

5,android 图片加载框架有哪些,对比下区别

6,图片框架的一些原理知识

7,其他的一些Android的模块化开发,热更新,组件化等知识。

三面;主流框架

在Android面试的时候,经常会被问到一些Android开发中用到的一些开发框架,如常见的网络请求框架Retrofit/OkHttp,组件通信框架EventBus/Dagger2,异步编程RxJava/RxAndroid等。结合本次面试,整理下上面的几个框架,大家可以拿去,面试备用

1. EventBus

EventBus是一个Android发布/订阅事件总线,简化了组件间的通信,让代码更加简介,但是如果滥用EventBus,也会让代码变得更加辅助。

面试EventBus的时候一般会谈到如下几点

(1)EventBus是通过注解+反射来进行方法的获取的

(2)使用ConcurrentHashMap来保存映射关系 调用实体的构建:调用实体中对于Object,也就是实际执行方法的对象不应该使用强引用而是应该使用弱引用,因为Map的static的,生命周期有可能长于被调用的对象,如果使用强引用就会出现内存泄漏的问题。

(3)方法的执行 使用Dispatcher进行方法的分派,异步则使用线程池来处理,同步就直接执行,而UI线程则使用MainLooper创建一个Handler,投递到主线程中去执行。

2.Retrofit

要明确EventBus中最核心的,就是动态代理技术。

Java中的动态代理:

首先动态代理是区别于静态代理的,代理模式中需要代理类和实际执行类同时实现一个相同的接口,并且在每个接口定义的方法前后都要加入相同的代码,这样有可能很多方法代理类都需要重复。而动态代理就是将这个步骤放入运行时的过程,一个代理类只需要实现InvocationHandler接口中的invoke方法,当需要动态代理时只需要根据接口和一个实现了InvocationHandler的代理对象A生成一个最终的自动生成的代理对象A_。这样最终的代理对象A_无论调用什么方法,都会执行InvocationHandler的代理对象A的invoke函数,你就可以在这个invoke函数中实现真正的代理逻辑。

Retrofit中的动态代理

Retrofit中使用了动态代理是不错,但是并不是为了真正的代理才使用的,它只是为了动态代理一个非常重要的功能,就是“拦截”功能。我们知道动态代理中自动生成的A_对象的所有方法执行都会调用实际代理类A中的invoke方法,再由我们在invoke中实现真正代理的逻辑,实际上也就是A_的所有方法都被A对象给拦截了。 而Retrofit的功能就是将代理变成像方法调用那么简单。

Retrofit作用

Retrofit实际上是为了更方便的使用Okhttp,因为Okhttp的使用就是构建一个Call,而构建Call的大部分过程都是相似的,而Retrofit正是利用了代理机制带我们动态的创建Call,而Call的创建信息就来自于你的注解。

3.OkHttp

请求任务队列

Okhttp使用了一个线程池来进行异步网络任务的真正执行,而对于任务的管理采用了任务队列的模型来对任务执行进行相应的管理,有点类似服务器的反向代理模型。Okhttp使用分发器Dispatcher来维护一个正在运行任务队列和一个等待队列。如果当前并发任务数量小于64,就放入执行队列中并且放入线程池中执行。而如果当前并发数量大于64就放入等待队列中,在每次有任务执行完成之后就在finally块中调用分发器的finish函数,在等待队列中查看是否有空余任务,如果有就进行入队执行。Okhttp就是使用任务队列的模型来进行任务的执行和调度的。

复用连接池

Http使用的TCP连接有长连接和短连接之分,对于访问某个服务器的频繁通信,使用短连接势必会造成在建立连接上大量的时间消耗;而长连接的长时间无用保持又会造成资源你的浪费。Okhttp底层是采用Socket建立流连接,而连接如果不手动close掉,就会造成内存泄漏,那我们使用Okhttp时也没有做close操作,其实是Okhttp自己来进行连接池的维护的。在Okhttp中,它使用类似引用计数的方式来进行连接的管理,这里的计数对象是StreamAllocation,它被反复执行aquire与release操作,这两个函数其实是在改变Connection中的List<WeakReference<StreamAllocation>>大小。List中Allocation的数量也就是物理socket被引用的计数(Refference Count),如果计数为0的话,说明此连接没有被使用,是空闲的,需要通过淘汰算法实现回收。

4. RxJava

从15年开始,前端掀起了一股异步编程的热潮,在移动Android编程过程中,经常会听到观察者与被观察者等概念。

观察者与被观察者通信

Observable的通过create函数创建一个观察者对象。

public final static Observable create(OnSubscribe f) {

return new Observable(hook.onCreate(f));

}

Observable的构造函数如下:

protected Observable(OnSubscribe f) {

this.onSubscribe = f;

}

创建了一个Observable我们记为Observable1,保存了传入的OnSubscribe对象为onSubscribe,这个很重要,后面会说到。

onSubscribe方法

public final Subscription subscribe(Subscriber<? super T> subscriber) {

return Observable.subscribe(subscriber, this);

}

private static Subscription subscribe(Subscriber<? super T> subscriber, Observable observable) {

总结

学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

最后如何才能让我们在面试中对答如流呢?

答案当然是平时在工作或者学习中多提升自身实力的啦,那如何才能正确的学习,有方向的学习呢?有没有免费资料可以借鉴?为此我整理了一份Android学习资料路线:

这里是一部分我工作以来以及参与过的大大小小的面试收集总结出来的一套BAT大厂面试资料专题包,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家。

好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划。来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。

最后,祝愿即将跳槽和已经开始求职的大家都能找到一份好的工作!

这些只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢再关注一下
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家。

[外链图片转存中…(img-00NYZEyN-1714936367480)]

好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划。来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。

最后,祝愿即将跳槽和已经开始求职的大家都能找到一份好的工作!

这些只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢再关注一下
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 28
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值