面试心得,与君共勉
简书作者:PurpleSense

编者按:本博文主要记录今天参加阿里巴巴内推一面的面试流程和题目,同时会记载我当时的回答,以做一个记录,便于日后回顾。观者如对本文的写作有任何建议,或者对今天的题目有更好的见解的话,欢迎下方评论交流,小编我在此先行谢过了!如果有问题想咨询的话,也请在下方的评论区表达,我看到会回复你们的。
Timeline:内推时间(3.1)-->预约面试(3.2)-->一面(3.4)由时间线可知,阿里的效率真不是盖的,小编我都没来得及好好准备
临时抱佛脚:3.2晚上8:11,当时刚被阿里的编程测验虐完,正在做素质测评题的时候,接到了来自浙江杭州的电话,纠结了一下后关了测评题,接了电话。开始还担心这是突袭面试呢,接了电话才知道这次是和我预约一个时间进行面试(这一点真得给阿里郎点一个大大的赞)。由于我第二天上午预约了牙医,所以经过沟通后,我们预约了3月4日下午2:00进行第一轮电话面试。也就是说复习时间只有一天半,真的完全不够用,所以只能做一些临时抱佛脚的工作。

  • 测试知识:我投的岗位是测试开发,本以为会问一些关于测试方面的知识,所以就先突袭了下这一块知识,主要准备的内容包括:测试分类、各类测试含义、测试流程、测试方法、设计测试用例、基本的测试工具(注:由于小编我之前在百度公司进行过一段时间的测试开发工程师的实习工作,所以这一块知识捡起来会相对容易一些,大概利用3.3下午看了一个下午,稍微过了一遍就了事了)
  • 计算机基础知识:考虑到各大公司在校招时都挺注重一些计算机基础知识的,而很久没有看过这些知识的我,已然忘得差不多了,所以赶紧补一下。然而时间太紧张了,所以只能挑几个点复习一下,碰碰运气了。3.3晚上复习的点有:TCP/IP三次握手、四次挥手机制、HTTP响应码、Get和Post请求的区别、Cookie和Session的区别、TCP和UDP的区别、OSI七层网络模型和TCP/IP五层网络模型。就这些了,一个晚上真做不了什么事情(/衰)
  • 简历:3.4上午先复习了一下3.3的知识,然后就针对自己的简历做了一点小小的准备,不过其实也就准备了一下自我介绍和项目介绍,因为自己的专业技能点那一块由于没有复习很好,所以写得比较宽泛,完全不适合这种突袭复习,也就没怎么准备了。
面试:
14:19,来自浙江杭州的电话如期而至。稍等了3秒后,接起了电话。对方确认我可以开始面试后,我的面试就正式开始了。
Q & A:

  • Q: 你之前有做过哪些项目没有?
    A: 我之前做过一个Android APP项目,然后还参与了一个Android APP项目,然后就是两个实现的研究性的项目。(点评:这一部分其实可以展开介绍我的项目的,然而当时晕菜了,没有注意到)
  • Q: 你的研究方向是什么?
    A: 我们实验室的研究方向是自然语言处理,其中我做的工作主要是通过挖掘微博文本中的数据来分析得到微博中的突发话题。
  • Q: 你简历中写到你比较熟悉Java开发,那么你平时有用到哪些集合类呢?
    A: 我平时使用HashMap、ArrayList、LinkedList比较多,而TreeMap、HashSet这些平时会使用得少一些,也就没怎么研究。(点评:当时心理挺希望他继续问一些有关HashMap、ArrayList、LinkedList相关的问题的,因为之前有研究过这几个类的源码,但是又害怕会问到另外的一些类相关问题,所以没敢多说)
  • Q: 你能说一说这些集合类之间都有哪些区别么,从大的方向上说。
    A: 确认了他主要是问Set、Map、List之间的区别后,我便回答说:Set中只能存放非重复的元素,并且这些元素是无序的;List中能够保存重复性的元素,因为List中的数据是有序的,元素的有序性就保证了存储相同元素也能区分;而Map是不同于Set和List的一个数据结构,Map中存放的是键值对形式的数据,并且Map中的键是不能重复的,但是值可以重复。正是因为Map中键的不可重复性,所以这便是一个很好的Set类。Java开发者很好地利用了这一点,Java中HashSet就是直接使用了HashMap的键来实现的,这样的话,一个实现类就能够完成两个数据结构的功能,即减少了开发、维护成本,又降低了编程人员的学习成本,是一个非常好的学习案例,值得我们学习。
  • Q: 你的项目都是Android客户端开发,那你有没有接触过一些B/S开发呢,比如说服务器端的开发?
    A: 呃。。。sorry了,并没有,只能如实说了。
  • Q: 你之前有在项目中或者自己有进行过多线程并发编程没?
    A: 呃。。。还是没有(/衰,至此感觉很不好)
  • Q: 既然你没使用过多线程,那么现在问你一些线程的基本知识,线程有哪几种创建方式,如何启动一个线程?
    A: 可以通过两种方式创建线程,一种是通过继承Thread类创建,另一种是通过实现runnable接口来实现,可以在线程类中定制自己想要处理的任务,然后调用start方法启动这个线程(线程方面的知识应该还是蛮重要的,不过没怎么用,也没有复习,所以不怎么能讲出更多。)
  • Q: JVM的垃圾回收算法了解吗?
    A: 我个人觉得应该主要关注垃圾回收算法的如下几个问题:


  • 什么是垃圾?当程序中一个对象没有引用指向它的时候,便意味着这个对象很有可能在接下来的程序中不会再被用到,也就是说这个对象对我们的程序来说已经不再有价值,那么如果还让这个对象一直占据着这块内存的话,对我们的内存来说是一种浪费,况且现在的内存资源还挺紧张的,尤其是移动端应用。所以JVM就定义说:如果一个对象已经没有引用指向它了,那么就认为这个对象是一个垃圾对象,需要被回收掉,将内存空间释放给其它对象;
  • 如何判断一个对象是垃圾?既然我们要对那些垃圾对象进行回收,那么我们首先需要有一种算法能够识别出垃圾对象。开始的时候,使用的是一个称之为引用计数器的方法,也就是说,在我们创建一个对象的时候,JVM就会同时为这个对象分配一个引用计数器,每当有一个新的引用指向这个对象的时候,引用计数器加1,而当有一个引用脱离了这个对象的时候,引用计数器就减1。这样,在JVM进行垃圾回收操作的时候,通过判断一个对象的引用计数器是否为0便可以获知这个对象是否为一个垃圾对象。这种方式实现起来比较简单,但是有一个很严重的问题,就是不能处理循环引用问题。具体而言,就是当内存中存在循环引用时,这些循环引用的对象的引用计数器均不为0,也就是说这些对象均不能被判定为垃圾对象。但是也有可能这些循环引用作为一个整体是一个垃圾,这样的话,JVM无法对这一块内存进行回收,从而造成了内存的浪费。后面经过改进后,JVM采用了一种称之为根搜索的算法。这种算法的工作原理为:在创建一个对象的时候,会有一个由该对象指向一个称之为GC ROOT的对象的链接,如果在JVM进行垃圾回收操作时,某个对象有到GC ROOT的链接,即该对象是可达的,那么这个对象就不能被当作垃圾处理,否则如果某个对象到GC ROOT是不可达的,则认为该对象是一个垃圾对象,应该被回收掉。ok,至此,已经能够判断出什么样的对象是垃圾对象了。
  • 何时进行垃圾回收?JVM进行垃圾回收的时机并不是一成不变的,而是需要根据具体情况而定的。虽然编程人员不需要显式的对内存进行回收,但是不排除某些时候,编程人员会觉得在这一处需要进行垃圾回收操作,所以JVM给编程人员提供了一个使用GC操作的接口,通过这个接口,编程人员就可以通知系统说,我现在想要进行垃圾回收操作。不过这只是通知系统说,我想要执行GC操作了,而并不是直接调用GC,进行垃圾回收。系统接收到通知后,则会根据自己的策略来决定是立即执行GC操作,还是等下再执行。另一种情况就是在程序运行过程中,当我们需要一块比较大的内存,而现有的空闲内存空间已经不能满足需求的时候,JVM就会通过执行GC操作以求获得所需的内存空间。
  • 如何进行垃圾回收?最开始有一种垃圾回收策略是标记--清除策略,这种策略是说在进行GC操作时,将垃圾对象加上标记,然后将有标记的对象进行清除,从而达到释放垃圾对象的内存空间的目的。这种方式的优点是实现比较简单,但其缺点也是很严重的。因为采用这种方式进行垃圾回收后,得到的内存空间是零散的,所以经过几轮GC后,内存的碎片化会非常严重,从而导致某些原本可以存放的对象也因为没有一片足够大的连续内存区域而创建失败。后面经过改进后的一种垃圾回收策略为复制策略,该策略的思想为:首先将一片内存区域一分为二,然后先在其中一片区域中创建对象,等到需要进行垃圾垃圾回收操作时,将不是垃圾的对象复制到另一片内存区域,然后将这一片区域清空。经过复制后,所有的非垃圾对象都被重新排列到一片连续的内存区域中了,所以几乎不存在碎片化问题,然而该策略的缺陷在于一开始就需要将一片内存一分为二,交替使用,这样的话,内存利用率只有50%,利用率太低。所以JVM现在也没有采用这种方式。现在JVM采用的是一种分代回收的垃圾回收机制。该机制基于这样一个观察:在我们的应用程序中,大部分的对象的存活周期很短,只有一小部分对象的存活周期比较长。所以基于这样一个观察,JVM将一片内存区域分为两部分:新生代和年老代,其中新生代又按照8:1:1的比例分为生成区、From Survivor区 和 To Survivor区。创建一个对象时,先将这个对象放入生成区,当进行GC操作时,将没有引用的对象清楚,还幸存的对象放入From Survivor区,如果From Survivor区存放不下,再将对象移到年老代。其中这个算法的核心在于:每次进行GC操作时,都自动会对对象的生存期有一个记录机制,经过几轮GC操作后仍然存活的对象被认为是那些生存周期比较长的对象,而被加入年老代。采用这种方式进行GC操作既能避免内存的碎片化问题,又能拥有比较好的内存利用率。关于JVM的垃圾回收机制,我大概就知道这么多,谢谢!
  • (点评:一直觉得JVM的内存结构、垃圾回收机制这一块是一个重点,需要抽时间好好复习一下,不过这次时间太紧,也没来得及复习,就只能根据平时看到的博客内容结合自己的理解讲一下,讲得不是那么完善,很多地方还有遗漏)
Q: 你平时应该有接触到一些算法方面的知识的吧,现在问你一个算法类题目。现在给你两个文件,这两个文件格式相同,都是每行存储一个数字,但是数字的大小未知,文件的大小也未知,已知的是这两个文件都很大,无法一次性加载入内存进行处理。你的任务是求这两个文件的交集。
A: 这道题我一开始想的是采用分片读入内存,然后对每一个分片求交集,然后取并集的做法,经提醒后,这个方法存在一个问题:不在当前数据的交集中的数据并不一定不在整个文件的交集列表中。后来,我又想着说:只去除掉那些交集中的数据,而保留非交集的数据,继续与后面的数据进行比较。他听后很惊讶地说:你这样做,那时间复杂度会有多高呀(.../擦汗 我都能想象到他当时的表情)然后我就只能另想策略了,最后经过他的提醒,这道题应该先对两个文件进行预处理,即使用快排算法对这两个文件先排序,然后对这两个文件采用二路归并算法求交集。原来如此呀,我开始还在纠结引入排序算法的话,排序方面还会有时间消耗呢!!!(点评:平时没做过这类型题目,也没遇到过这类问题,所以一被问到,就蒙了)
Q: 你之前说你没有接触过网站端的开发 ,那问你一些比较简单的这方面的知识吧。你知道哪些服务端开发的框架呢,简单说一下。
A: 呃。。。有听说过SSH框架,即Struts+Spring+Hibernate,但没有用过。(现在很后悔当时J2EE课没有好好听了)
Q: 现在问你一个设计方面的问题,看一看你在设计方面的想法。现在有很多网站,比如说淘宝、天猫......然后需要实现一个功能就是多点同步登录,也就是说一个用户如果在这个网站上已经登录了,那么在另一个网站便可以免登录进入了。现在让你来实现这样一个功能,你会怎么设计?
A: 我觉得这个应该采用数据库共享机制来实现吧。也就是说,用户信息一般是保存在数据库表中的,其中会有一个字段表示用户当前状态:在线 or 离线。应用程序在启动的时候,先从数据库中读取这个字段的数据,如果结果显示用户在线的话,就直接让用户进入主界面,否则显示登录界面,让用户登录。不过这种实现机制一定要处理好并发问题,当多个应用程序对同一个字段进行读操作时是没有问题的,但是当同时进行写操作时就会有问题,所以应该对写操作进行处理。(这就引出了接下来这个问题)
Q: 如何控制并发访问?
A: 一般来说有三种机制:CAS原子锁、同步锁和Lock机制。(并发操作不是很熟悉,也就对每一种情况随便说了两句,就结束了)
Q: 你简历中写着你做过Android客户端开发工作,现在问你一个Android方面的问题:Android中activity的生命周期是怎样的?
A: onCreate-->onStart-->onResum-->onPause-->onStop-->onDestory(这是Android开发必备基础知识,所以不难,针对各种生命周期函数的变化情况大致说了一下)
Q: 你以往的开发经历中有没有遇到过一些令你印象深刻的难题、问题,你是如何解决的?
A: 这个之前在做项目过程中确实遇到过几个比较印象深刻的问题,当时还查阅了一番资料进行解决的,所以这个问题就是根据实情说的,不过由于之前没有准备,所以语言组织方面还需要加以思索。
Q: 你认为一份怎样的代码才能算一份好的代码?
A: 这个主要谈了一些有关代码规范的东西以及自己对一份可读性比较好的代码的看法。
Q: 你平时会不会自己学习一些东西,你有没有除Android以外自己比较感兴趣,但没有时间学习的知识?
A: 这个嘛,平时有看一些Android开发周报、开发者头条上面的文章,所以就说了一下这个。至于自己感兴趣的知识点的话,就说了一下自己还没有涉猎服务端开发项目和并发编程的一些操作,感觉这些知识更富有挑战一些,所以对这些东西有感兴趣,但还没来得及学(这是实话,呵呵哒)
Q: 看你平时都是做的实验室项目,你业余有没有自己做过一些小项目?
A: 之前周神(师兄)有想让我做一个小的练习项目来着,当时还挺有兴趣地各种查资料设计页面、设想功能来着,也写了一点代码,但后面开始看论文后,心里比较烦闷,就搁浅了。所以问到这个问题时,我就说了一下这个东东。他后面还主要问了一些设计方面的问题。
Q: 你平时都是怎么记录所学的知识的,有写博客之类的吗?
A: 我有写博客,博客上已经有几十篇文章了,不过还有许多文章未经修饰,所以还未公开。
最后,他说你等二面吧,我便知道一面已经过了。不过还是傻傻地问了一句:“这就意味这我通过了一面,对么?”他可能没想到我居然会问如此弱智的问题,回说:“你可以这样认为吧!”呵呵,哥哥,你就不能好好说话么,不过确认已经通过了一面还是蛮开心的,希望二面能顺利!
后面,我问了下在阿里里面测试和测开的区别,他很耐心地回答了这个问题。
A:阿里目前大的趋势是要尽可能减少传统的测试人员,而是都向测试开发转。其中主要有三类:(具体他讲得还是蛮详细的,但主要是一些思想性的东西,所以下面就记了个大概)

  • 会参与到产品研发过程中的与业务相关性比较高的测试人员,这类测试人员主要的工作为:需求分析、用例设计、测试执行、面向服务端的接口测试、面向客户端的UI自动化测试以及部分白盒测试工作等;
  • 开发测试工具,提供测试工具给开发进行自测;
  • 探索尝试新的测试思想、测试方案;
总结:

  • 深深地有一种被反套路了的感觉,大概面试官们已经知道我们会突袭哪些基础知识了,我这两天突袭的那些知识一个都没有派上用场,他完美地避开了我的复习点(/忧伤);
  • 虽然我面试的岗位是测试开发,但是通观整个面试过程,没有出现一个显式的测试相关类题目,开始还觉得奇怪,但最后听完他对阿里目前的测试现状及发展重点后,才理解原因,毕竟在阿里内部测试开发还是偏向于开发的。所以各位投了、欲投测试开发岗位的童子们,你们还是得好好准备下开发方面的知识,最好是能做一做项目;
  • 通观所有的测试题目,可以发现如下现象:


  • 面试的范围挺广的,涵盖了设计、项目、算法、数据结构、语言特性等;
  • 很关注你对技术的态度、你的学习能力、你能否从更高一层次来看问题;
  • 很注重观察你平时的技术积累;
虽然很幸运地通过了一面,但是从博客中可以看出,我今天的面试表现还是挺烂的,有些问题还没有怎么思考好就回答了、有些问题根本就不会、语言的临时组织能力还有待加强、平时做的一些事情缺乏深入的思考、一些比较难的问题(如并发编程等)会心存侥幸心理而没有关注、还不会引导面试流程,面试基本上处于你问我答的状态。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
共收到 0 条回复
暂无回复。
回帖
B Color Image Link Quote Code Smilies
Command + Enter
快速回复 返回顶部 返回列表