我的2017是忙碌的一年,从年初备战实习春招,年三十都在死磕JDK源码,三月份经历了阿里五次面试,四月顺利收到实习offer。然后五月怀着忐忑的心情开始了蚂蚁金服的实习。八月,又经历了两轮面试,总算拿到转正offer。到此为止,我总算可以尽情地享受最后的校园时光了。
希望我的经历与感悟能帮助到大家。
我的读研经历
阿里是我读研阶段的一个重要目标,刚上研一的时候我便立下Flag,计划了读研三年要做的事情、要学的东西。翻翻我的博客,居然还能找到当时写的读研计划(想想时间过的真的好快呀)。阿里在我心中一直是技术者的朝圣地,聚集了一群技术狂热分子,为了提升一点点的性能可以废寝忘食。在立下这个flag后,我便把我要去阿里的想法告诉了身边的所有人。我不想给自己留有后路,既然牛逼吹出去了,那就得落实到行动上。
我当时的计划是这样的,研一玩命做项目,毕竟写代码是一项孰能生巧的技术,多写代码自然能加深对技术的理解。事实也确实证明了这一点。我大四毕业的那个暑假,第一次接触《深入理解JVM虚拟机》,当时看完之后是一脸懵逼的,所有的汉字都认识,但连成一条句子后咋就不明白呢?然后怀着这种一脸懵逼的状态,强行把这本书看完了,但由于理解的不够深刻,很快就忘记了。然后经过一年疯狂做项目,当我再抱起这本书时,我对这本书的感觉有了180度的转变,通俗易懂啊。我怀疑自己当时为什么这么傻。而在这一年之内,我一共做了四个项目。所以说,写代码能潜移默化地提升你对技术的理解程度。
记得我们学校考研结果公布是在三月底,得知我录取了,短暂的高兴了一下,第二天便去了导师实验室,参与到项目中去。因为我心理很清楚,我的目标是阿里。
刚去实验室的时候感觉自己完全是一只小白,师兄们开会讨论的东西我竟然一个字都听不懂,刚开始分到的工作也很难顺利的完成。但我是一个天生不服的人,我越是不懂,我越是要征服。(PS:追女生也一样,当时看上了一个高冷型女神。越是高冷,我越要拿下……省略一万字……最后成功了)。我渐渐跟上了师兄们的步伐,从第二个项目开始,我一直是项目负责人了。
我给自己定的方向是Java,而实验室的项目五花八门,Qt、C++、图像图形……,但我心里清楚,这些项目可以拓宽我的视野,可以锻炼我的学习能力、思维方式,但要深入理解的技术还是Java。所以我利用项目空窗期,看了很多Java方面的书籍,文末我列了一份清单供大家参考。
研一做了一年项目之后,感觉自己解决问题的能力、快速上手新技术的能力有所提升,但做项目一味求快、一味赶时间,我对很多技术的理解仅停留表面。所以更多时候我感觉自己是在搬砖,很难写出高质量的代码。当时我决定,研二的上半学期一定要好好稳固基础,深入理解技术背后的原理,放慢做项目的节奏,不一味地盲目求快。
然而研二因为种种原因,我去了一家创业公司实习。既然我无法选择,那我就拥抱变化。既来之则安之,我希望自己所花的时间都有所收获。所以我全身心投入到工作中去。公司安排我做前端,虽然这并不是我想干的事情,但当前别无选择,既然做那就得做好。我花了一个月的时间怒刷前端知识,学习Angular、React,了解它们的设计思想,学习JS背后的原理,也看到了前端目前的发展状况。前端的技术迭代速度很快,但技术背后的原理都是类似的,所以抓住技术背后的本质才是最重要的。
这段实习一直持续到了今年一月,我心理清楚,二月底三月初阿里的实习招聘就要开始,所以我挤出中午休息时间、晚上下班后的时间、周末的时间,复习我之前积累的东西。
三月三号,人生的第一次面试,在看到杭州的电话时,那一刻的心情既忐忑又兴奋。在此之前,我并不清楚自己的水平在所有应届生中处于一个怎样的层次,在电话接通之前我已经做好了充分的心理准备,想象了各种被面试官吊打的画面。第一次面试持续了54分钟,面试官似乎破有耐心,整个面试过程相谈甚欢。那一次的面试给了我巨大的信心,因为我清楚,我离我的目标更近了一步。
在接下来的一个月中,我陆陆续续接到了五次面试电话,每一次面试都是一次学习的机会,能发现自己的不足,在与面试官交流的过程中也能了解到最新的技术、最佳的实现方法。
四月十四,记得那天刚替导师给本科生上完算法课,晚饭过后便收到的阿里的offer。当时的喜悦之情溢于言表,这么久的努力没有白费。但我心里也清楚,阿里的实习转正率向来很低,要想通过实习留下来也不是一件容易的事。所以在收到阿里offer之后的那晚,我重新规划了接下来的学习计划,将我的短期目标更新成:拿下阿里转正offer。
5.20,一个美好的日子,我怀着憧憬、忐忑、兴奋的心情走进了支付宝大楼,开始了我三个月的实习生涯。这三个月的实习让我学到了很多,我看到了每天的进步,也看到了自己的不足。这100天经历了太多的事情,有太多的体会,有空我再单独写一篇实习期间的感悟与大家分享。
9.1晚上11点,我的状态从『面试中』变成了『待跟进offer』,我会心一笑,我达成了人生第一阶段的目标。那一刻我没有太多的激动,在经过了2017年8个月的持久作战之后,这个offer早已在我的意料之中。
第二天是周六,这个周末我给自己放了两天的假。虽然在杭州已经呆了102天,虽然支付宝大楼就在西湖边,但每天两点一线的工作,我并没有去过西湖。那一晚我的基友得知我收到offer后便立即买票,坐了一夜的火车来杭州为我庆祝。也托他的福,在这个周末我第一次游览了这座美丽的城市。
最后的校园时光,我给自己定了一个新的目标,这个目标也许充满了挑战、充满了艰辛与困难,但我想如果能达成,我的人生将会有很大的改变。在人生的路上,我还在奋斗。希望与各位共勉。
一些建议
在面试阿里的过程中,博客帮了我很大的忙。并不是说有博客在面试中会加分,而是写博客的过程能加深你对知识的理解,而且回顾起来也特别高效(毕竟是自己写的东西)。
我从研一开始便养成了写博客的习惯,现在先过头来,这两年我一共写了185篇文章,有22W的访问量,也很荣幸称为专家博主。我的博客现在已经成为我一笔最宝贵的财富,记录了我技术的整个体系结构,也记录了学习技术的心路历程。
可能很多同学都有写博客的经历,但能长期坚持的少之又少。我想告诉大家,任何事情都贵在坚持。只要坚持21天就能养成习惯。有的时候对这件事缺乏兴趣了很难再持续下去,但想想自己的目标,咬咬牙坚持下去,养成习惯你就赢了。
我的博客一般都是看完一本书后的总结,我会把一本书中最核心的东西,按照我的理解把它们记录下来。每一本书我都会看三遍,第一遍是快速浏览,了解整本书的体系结构、作者的行文思路,知道书中重要的、不重要的内容,也就是要建立起全局观。第二遍我会精读,把那些我认为重要的内容挑选出来着重阅读、反复理解、吃透。第三遍阅读,往往会冒出新的理解,我时常有这种『书读百遍,其义自见』的感觉。三遍读完后,我便按照自己的理解,把核心内容写成博客。由于是自己的写的东西,所以在复习的时候只要花上三五分钟通读一遍,所有的知识点又被唤醒。
Java面试考点梳理
本文是根据我的面试经验,为大家整理Java程序猿面试所需的知识体系。
第一部分:计算机基础
互联网大厂都相当重视程序员的基本功,也就是计算机基础知识。一个程序员能走多远、爬多高,很大程度上取决于基本功是否扎实。对于应届生而言,大都比较缺乏实战项目经验,虽然会有一定的项目经验,但这些课程设计、实验室项目的质量与公司实际的项目有着巨大的差距。因此,基础知识便成为面试考量的一大重点,而且基础扎实的程序员可塑性比较高,做什么都能比较容易快速上手。
计算机基础包含如下几门课程,相信计算机专业的同学肯定都已经学过。但互联网公司面试的考点可能和你们期末考试的考点有一些不同,我都做了整理。
1. 计算机网络
大学课程中的计算机网络一般都按照OSI七层参考模型介绍,然而由于互联网公司的特性,他们更加关注日常开发所涉及到的传输层和应用层,所以需要重点掌握传输层和应用层中所涉及到的所有知识点。
【考点】
- 传输层的作用
- 传输层复用和分用的含义
- 传输层和网络层的区别
- UDP协议的特点
- UDP协议的报文结构
- TCP协议的特点
- TCP协议的报文结构
- TCP三次握手过程
- TCP四次挥手过程
- TCP可靠传输是如何实现的
- 停止等待协议
- 滑动窗口协议
- TCP的流量控制
- TCP拥塞控制
-
HTTP协议
- HTTP工作流程
- HTTP请求格式
- HTTP 1.1中的8种请求方式
- HTTP响应格式
- HTTP中重要的请求头和响应头字段
- HTTP常用状态码及其含义
-
HTTPS协议
- HTTPS协议与HTTP协议的区别
- HTTPS协议的工作流程
【资料整理】
- 计算机网络传输层知识点全覆盖-大闲人柴毛毛的博客
- HTTP详解(1)-工作原理
- HTTP详解(2)-请求、响应、缓存
- HTTP详解(3)-http1.0 和http1.1 区别
- 图解 HTTPS 通信过程
2. 数据结构
熟练掌握数据结构是程序员最最最基本的素养,在实际开发中选择合适的数据结构将极大影响程序的效率。面试官一般并不会直接问数据结构的问题,而是通过出一些包含数据结构的算法题来考察你对数据结构的理解程度以及在实际项目中是否能够灵活应用。你可以通过刷算法题来提升这部分能力,推荐《剑指offer》和《程序员面试金典》(注意是金典!)。很多公司的算法题库都选自这两本书。
当然,刷这两本书的目的并不是让你死记硬背题目,题目千变万化,面试官可以随意改变。刷算法题最重要的是培养解决问题的思路和解决实际问题的能力。在刷题的过程中要多多总结,再次强调,切忌死记硬背!
3. 算法
和数据结构一样,算法一般也通过具体的算法题来考察,你也可以通过刷《剑指offer》和《程序员面试金典》中的算法题来提高这方面的技能。但在刷这些算法题之前,你需要掌握几类基础的算法,并理解他们解决问题的思路(这才是最为关键的)。这些算法我已经在下面整理。
4. 操作系统
【考点】
- 操作系统的四个特性。
- 操作系统的主要功能。
- 进程的有哪几种状态,状态转换图,及导致转换的事件。
- 进程与线程的区别。
- 进程通信的几种方式。
- 进程同步的几种方式
- 用户态和核心态的区别。
- 死锁的概念,导致死锁的原因。
- 导致死锁的四个必要条件。
- 处理死锁的四个方式。
- 预防死锁的方法、避免死锁的方法。
- 进程调度算法。
- 内存连续分配方式采用的几种算法及各自优劣。
- 基本分页储存管理方式。
- 基本分段储存管理方式。
- 分段分页方式的比较各自优缺点。
- 几种页面置换算法,会算所需换页数
- 虚拟内存的定义及实现方式。
【资料整理】
5. 数据库
【考点】
- 什么是索引?
- 索引的分类
- 索引的优缺点分析
- 何时需要使用索引?何时无需使用索引?
- 什么是事务?
- 事务的四大特性
- 数据库三大范式
- 数据库有哪些表连接?
【资料整理】
第二部分:Java
作为一名合格的Java程序员,仅了解如何使用Java是远远不够的。你能够熟练使用Java只能说明你已经成为一名合格的码农,能够利用Java实现某些功能。而公司作为盈利机构,需要用最少的资源实现效益最大化,这就需要程序员具备高质量代码的能力,而能否写出高质量代码取决于你对技术背后原理的理解程度。只有在理解Java背后的原理,你才能根据Java的特性,写出更加高效的代码。这在实际业务中是非常有价值的事情。互联网大厂服务海量用户,更加注重系统的性能,也更加注重程序员对原理的理解。
关于Java的基础知识和如何使用,这里我就不提了,随便一本Java书籍都有详细的介绍。这里我整理了Java原理性的知识点,这些知识点将会成为你面试的加分项。
1. Java虚拟机
【考点】
-
Java虚拟机内存模型特点和作用
- 程序计数器
- Java虚拟机栈
- 本地方法区
- 堆
- 方法区
- 对象创建过程
- 对象访问过程
- 对象的内存结构
- 垃圾收集算法
- 如何判定哪些对象需要回收?
- 对象内存分配策略
- 分配担保机制
- 垃圾收集器的比较
- Class文件结构
- 类加载的时机
- 类加载过程
- 双亲委派模型
【知识点资源整理】
- 深入理解JVM(一)——JVM内存模型
- 深入理解JVM(二)——揭开HotSpot对象创建的奥秘
- 深入理解JVM(三)——垃圾收集策略详解
- 深入理解JVM(四)——对象内存的分配策略
- 深入理解JVM(五)——HotSpot垃圾收集器详解
- 深入理解JVM(六)——JVM性能调优实战
- 深入理解JVM(七)——Class文件结构
- 深入理解JVM(八)——类加载的时机
- 深入理解JVM(九)——类加载的过程
- 深入理解JVM(十)——类加载器
2. Java并发编程
【考点】
- 什么是死锁?如何避免死锁?
- 什么是重排序?
- volatile有哪些特性?
- 什么是内存可见性?
- volatile为什么能够保证内存可见性?
- 中断机制
- 线程通信有哪些方式?
- 线程池的作用?
- ThreadPoolExecutor如何使用?
- 如何设置线程池的大小?
- 如何保证线程安全?
- JDK 1.6哪些对锁做了哪些优化?
【知识点资源整理】
- Java并发编程的艺术(一)——并发编程需要注意的问题
- Java并发编程的艺术(二)——重排序
- Java并发编程的艺术(三)——volatile
- Java并发编程的艺术(四)——线程的状态
- Java并发编程的艺术(五)——中断
- Java并发编程的艺术(六)——线程间的通信
- Java并发编程的艺术(七)——Executors
- Java并发编程的艺术(八)——闭锁、同步屏障、信号量详解
- Java并发编程的艺术(九)——批量获取多条线程的执行结果
- Java并发编程的艺术(十)——线程池(1)
- Java并发编程的艺术(十一)——线程池(2)
- Java并发编程的艺术(十二)——线程安全
- Java并发编程的艺术(十三)——锁优化
- Java并发容器大合集
3. Java 容器考点及资料整理
- Java 集合系列01之 总体框架
- Java 集合系列02之 Collection架构
- Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
- Java 集合系列04之 fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)
- Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例
- Java 集合系列06之 Vector详细介绍(源码解析)和使用示例
- Java 集合系列07之 Stack详细介绍(源码解析)和使用示例
- Java 集合系列08之 List总结(LinkedList, ArrayList等使用场景和性能分析)
- Java 集合系列09之 Map架构
- Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例
- Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
- Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例
- Java 集合系列13之 WeakHashMap详细介绍(源码解析)和使用示例
- Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
- Java 集合系列15之 Set架构
- Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例
- Java 集合系列17之 TreeSet详细介绍(源码解析)和使用示例
- Java 集合系列18之 Iterator和Enumeration比较
4. Java IO 考点及资料整理
- java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括InputStream)
- java io系列03之 ByteArrayOutputStream的简介,源码分析和示例(包括OutputStream)
- java io系列04之 管道(PipedOutputStream和PipedInputStream)的简介,源码分析和示例
- java io系列05之 ObjectInputStream 和 ObjectOutputStream
- java io系列06之 序列化总结(Serializable 和 Externalizable)
- java io系列07之 FileInputStream和FileOutputStream
- java io系列08之 File总结
- java io系列09之 FileDescriptor总结
- java io系列10之 FilterInputStream
- java io系列11之 FilterOutputStream
- java io系列12之 BufferedInputStream(缓冲输入流)的认知、源码和示例
- java io系列13之 BufferedOutputStream(缓冲输出流)的认知、源码和示例
- java io系列14之 DataInputStream(数据输入流)的认知、源码和示例
- java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
- java io系列16之 PrintStream(打印输出流)详解
- java io系列17之 System.out.println("hello world")原理
- java io系列18之 CharArrayReader(字符数组输入流)
- java io系列19之 CharArrayWriter(字符数组输出流)
- java io系列20之 PipedReader和PipedWriter
- java io系列21之 InputStreamReader和OutputStreamWriter
- java io系列22之 FileReader和FileWriter
- java io系列23之 BufferedReader(字符缓冲输入流)
- java io系列24之 BufferedWriter(字符缓冲输出流)
- java io系列25之 PrintWriter (字符打印输出流)
- java io系列26之 RandomAccessFile
- 深入分析 Java I/O 的工作机制
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。