但是科班程序员对这个问题感受好像并没有那么强烈,硕士毕业直接进入互联网公司工作的一位程序员说:“员工间谈不上鄙视,主要是看他们做的工作是不是好,但是一般情况下,培训班出来的工作质量不会太好。代码混乱、质量低、bug 多、没法维护,别人接手你的代码会很难受。”
“大家都是打工的,没有人会管你是哪里出来的。**我们只会鄙视那些技术垃圾的、配合不了的。**至于你是哪里出来的,并不会很在意。”补充道。
对于这个问题,某互联网公司技术总监曾经说过:外界的确存在一些公司认为培训班出来的程序员是“速成品”,然后卡简历的情况。“其实不是说培训机构出来的程序员表现都不行,只是表现不好的程序员可能都有过培训经历,行业里一传十、十传百就会认为培训机构出来的程序员都不行。”
培训 + 外包拿下字节的历程
我认识的一位培训+外包出身的程序员,目前开发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方法
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
负担。**
[外链图片转存中…(img-6mtt1apk-1715793170459)]
[外链图片转存中…(img-fHPFSnx6-1715793170460)]
[外链图片转存中…(img-vufsIOvO-1715793170461)]
[外链图片转存中…(img-hXq2WFAq-1715793170462)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!