对于培训出身的程序员
圈子里,科班程序员“鄙视”培训机构程序员仿佛曾经隐隐成了一种共识。
“培训机构进去的程序员简直什么也不会。不必看技术,刚刚培训进去的就是假大空。”网上甚至有更偏激的观点:培训班进去的全是垃圾,没有例外。
“培训机构进去的程序员基础薄弱很多,对某项语言可能有点相熟然而很死板,代码环境一变可能就不会了,更差点的就间接被当成‘敲代码机器’了。很多人刚进去没有残缺的案例操作,对这个行业还没有根底的认知,更别提思维、格局了。”
外界的这些舆论无形中成为这些程序员心中的刺。很多培训机构进去的程序员在面试时是不会通知用人单位培训背景的,有些人甚至会刻意瞒哄这段经验。“好多人被公司晓得后就间接被解雇了,有的人还背着房贷、要奉养老人,但也没有方法。”
在很多人看来,培训机构其实是复制粘贴进去一堆差不多的人。“人家用大学四年打下基础,你培训几个月速成,很难齐全领悟。”
然而科班程序员对这个问题感触如同并没有那么强烈,硕士毕业间接进入互联网公司工作的一位程序员说:“员工间谈不上鄙视,次要是看他们做的工作是不是好,然而个别状况下,培训班进去的工作品质不会太好。代码凌乱、品质低、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]); } } //办法2public void setParted1(int[] a,int left,int right){ if(left>=right||left==a.length||right==0){ 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||left==a.length||right==0){ 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 <T> Observable<T> create(OnSubscribe<T> f) { return new Observable<T>(hook.onCreate(f));}
Observable的构造函数如下:
protected Observable(OnSubscribe<T> f) { this.onSubscribe = f;}
创立了一个Observable咱们记为Observable1,保留了传入的OnSubscribe对象为onSubscribe,这个很重要,前面会说到。
onSubscribe办法
public final Subscription subscribe(Subscriber<? super T> subscriber) { return Observable.subscribe(subscriber, this);}private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) { ... subscriber.onStart(); onSubscribe.call(subscriber); return hook.onSubscribeReturn(subscriber);}
线程切换过程(Scheduler)
RxJava最好用的特点就是提供了不便的线程切换,但它的原理归根结底还是lift,应用subscribeOn()的原理就是创立一个新的Observable,把它的call过程开始的执行投递到须要的线程中;而 observeOn() 则是把线程切换的逻辑放在本人创立的Subscriber中来执行。把对于最终的Subscriber1的执行过程投递到须要的线程中来进行。
Android进阶之路
对咱们开发者来说,肯定要打好根底,随时筹备战斗 。不管寒冬是否到来,都要把本人的技术做精做深。尽管目前挪动端的招聘量的确变少了,但中高端的职位还是很多的,这阐明行业只是变得成熟标准起来了。竞争越强烈,产品质量与留存就变得更加重要,咱们进入了技术赋能业务的时代。
技术之路就是漫长的打怪降级,一直学习前人的踩坑教训能力晋升本人,切忌闭门造车! 所谓独乐乐不如众乐乐,在我过后确立好Android方向时,就曾经开始梳理本人的成长路线了,包含技术要怎么系统地去学习,都列得十分具体,收费分享给大家。
从架构根底开始,分了8个模块来逐渐从根底进阶到架构师的环节:
架构师筑基语言根底
目前Android APP开发支流语言就是Java语言,Java语言最大的个性就是进步了软件的交互可能性,能够说安卓手机简直所有应用程序都是利用Java语言来进行编写的。
设计思维解读开源框架
随着互联网企业的一直倒退,产品我的项目中的模块越来越多,用户体验要求也越来越高,想实现小步快跑、疾速迭代的目标越来越难,插件化技术利用而生。如果没有插件化技术,美团、淘宝这些集成了大量“app”的利用,可能会有几个g那么大。
所以,当今的Android挪动开发,不会热修复、插件化、组件化,80%以上的面试都过不了。
360°全方位性能调优
在不同档次的开发工程师手里,因为技术水平的参差不齐,即便很多手机在跑分软件性能十分高,关上利用仍然存在卡顿景象。
另外,随着产品内容迭代,性能越来越简单,UI页面也越来越丰盛,也成为晦涩运行的一种妨碍。综上所述,对APP进行性能优化已成为开发者该有的一种综合素质,也是开发者可能实现高质量应用程序作品的保障。
Android框架体系架构
Android开发者也往往因为网上Copy代码习惯了而导致对这块常常“应用”的代码相熟而又生疏:相熟的是简直天天在和它们打交道, 天天在复制这些代码 ;生疏的是尽管天天和这些代码打交道,然而并没有深入研究过这些代码的原理,代码深处的外延。
NDK模块开发(音视频开发系列)
在Android中,NDK是一系列工具的汇合,次要用于扩大Android SDK。NDK提供了一系列的工具能够帮忙开发者疾速的开发C或C++的动静库,并能主动将so和Java利用一起打包成apk。
Flutter学习进阶
自2020 年来无疑是 Flutter 技术热火朝天倒退的一年。当初这门技术也仍然十分有价值。
每一个挪动开发者都在为 Flutter 带来的“疾速开发、富裕表现力和灵便的 UI、原生性能”的特色和理念而痴狂,从超级 App 到独立利用,从纯 Flutter 到混合栈,开发者们在不同的场景下乐此不疲的摸索和利用着 Flutter 技术,也在面临着各种各样不同的挑战。
微信小程序开发
微信小程序作为当初比拟火的编程开发利用场景之一,深受市场的青眼,这让不少开发者眼馋不已。然而对于初学者来说,就齐全摸不着头脑了,不晓得微信小程序开发制作须要学习那些常识,有须要的敌人能够参考本篇。
最初分享一份面试宝典,祝每个人面试顺利。
Android BAT高级开发面试题及答案解析
面试的前一周工夫内,就能够开始刷题冲刺了。请记住,刷题的时候,技术的优先,算法的看些根本的,比方排序等即可,而智力题,除非是校招,否则个别不怎么会问。
以上内容均收费分享给大家,须要完整版的敌人,点这里能够看到全部内容。或者点击 【这里】 查看获取形式。
最初一些思考:
我有时候常常会思考,当前Android开发该往什么方向走?当初咱们所把握的技术当前会不会被代替淘汰?
哪些方向会成为相对支流方向呢?
像现在前景比拟好的音视频来说,并不是用Android去开发,而属于NDK开发,用的C++语言。
Flutter跨平台开发当初只是一种抉择,面试加分项,理论用的公司不多。
人工智能方向,门槛对于大多Android开发来说很高,没有相干业余的名校硕士学历很难入场,对数据结构算法等要求很高。
将来有点难以掌控的感觉。然而还好,能够掌控当初。技术无止境,不能进行学习。如果不能引领潮流,那就做一个跟随者吧!