美文网首页Java 杂谈程序员程序人生
面试处处碰壁?教你一招,心仪offer十拿九稳。

面试处处碰壁?教你一招,心仪offer十拿九稳。

作者: 4bfeaf8c2970 | 来源:发表于2019-03-20 13:43 被阅读61次

    很多同学面试前为面试做了充足的准备,但是一旦开始面试起来还是碰到一些之前没遇到过的问题,最后遗憾的丢失掉心仪的offer。

    在这里希望大家永远记住面试中的一条铁律:在你还没开始面试之前,单纯只是自己在家里准备,你永远没法做到100%完美的准备,一定会有这样那样的一些问题是内没注意到的,没准备好的。

    那么一个合理的面试策略应该是什么样子的呢?

    其实说来也很简单马,你需要把你的面试阶段划分为前中后三个阶段。

    (1)第一个阶段:练手

    当你觉得自己充分的准备好了面试之后,你应该先找几个感觉对自己会有一定技术挑战的公司,但是并不是自己特别意向想要去的公司去投递简历面试一下。

    在这个阶段,十有八九会暴露出来你很多的问题。

    对于很多人来说,别看可能是去一些中小型的互联网公司去面试,但是其实里面也有一些技术不错的面试官,只要面试官的技术实力比你强,那么在面试的过程中,一定会问到你一些问题,是你之前没注意以及没准备好的。

    此时你很可能会发现,刚开始面试的头三四家公司,每家公司聊的都不太顺畅,每家公司总有那么几个问题没回答好,然后都没拿到offer。

    但是这个阶段的好处是,你发现了自己很多薄弱环节,这个时候你应该尽快通过上网查资料的方式填补好自己对一些薄弱问题的弱项。

    然后迅速总结,内化为自己的语言,并且能落地到纸上画图实现。这样,下次再问到相同问题的时候,可以回答的更好。

    基本上按照之前很多同学的情况来说,大概第一个阶段就是持续个三家到五家公司那样子,但是这个期间你会瞬间发现自己很多的问题,然后短时间内通过查阅资料的方式就可以尽快弥补好自己没准备好的一些地方。

    (2)第二个阶段:冲刺

    经过了第一个阶段的被虐之后,每个人的面试能力都会加强很多,而且找到了一些面试的感觉,对面试的节奏、对答都有了更好的把控。

    这个时候第二个阶段,就可以尝试去冲刺一下阿里、美团、滴滴等国内的一些大厂了。

    在这个阶段里,你需要全力以赴去面试,如果你准备的很充分,经过了第一阶段的打磨提升了面试能力和经验,而且本身的一些学历、过往公司履历相对较好,同时你的一些软素质比如说学习能力、表达能力、沟通能力都比较好,那么在这个阶段相对就会有更大的把握拿到大厂的offer了。

    但是如果冲刺了一些大厂之后,感觉还是有一定的差距导致没拿到大厂的offer呢?其实这也是很正常的一个现象,因为毕竟大厂的面试官问的问题可能会更难,让你更加难以承受,可能会暴露出来你更多的问题。

    在面大厂的过程中暴露出来的问题,很多时候就不是准备充分与否的问题了,而是可能暴露出来你的技术能力和知识体系的欠缺,很多东西可能你根本就不会。

    这对你来说是好事情,因为你通过面试大厂,瞬间会明白自己跟大厂之间的技术差距。

    这个时候有些技术能力跟大厂欠缺很大的同学一下子会被极大的打击自己的自信心,建议大家暂停一下面试的过程。

    这时,你完全可以将面大厂过程暴露出来的自己的技术能力的欠缺记录一个清单,然后有针对性的找一些技术资料来对这些不足之处进行学习和准备,尽可能的弥补自己的欠缺。

    (3)第三个阶段:收尾

    假如说你的面试进行到了这个阶段,那么很不好意思,说明几个你最心仪的大厂没能进去。不过也没关系,这个时候如果你针对自己的技术短板进行突击学习之后,相信你的技术能力又会有一个成长和提高。

    此时你就应该针对你的跳槽进行收尾了,这个时候你可以投递一些中大型互联网公司的职位,同时再加上一些比较好的独角兽企业的职位,或者是一些你感觉技术氛围比较好的中小型互联网公司的职位。

    从笔者指导过的一些同学来看,你的面试能力积累到这个程度,基本上拿下一些offer是已经没问题了,你面试的时候都会比较游刃有余了。

    然后接着就可以在收获的几个比较好的offer里选择一个各方面最适合自己的offer。

    我在 Oracle 已经工作了近 7 年,面试过从初级到非常资深的Java工程师,且由于 Java 组工作任务的特点,我非常注重面试者的计算机科学基础和编程语言的理解深度,可以不要求面试者非要精通 Java。所以,如果你对 C/C++ 等其他语言能够掌握得非常系统和深入,也是符合需求的。

    工作多年以及在面试中,我经常能体会到,有些面试者确实是认真努力工作,但坦白说表现出的能力水平却不足以通过面试,通常是两方面原因:

    1、“知其然不知其所以然”。做了多年技术,开发了很多业务应用,但似乎并未思考过种种技术选择背后的逻辑。坦白说,我并不放心把具有一定深度的任务交给他。

    2、知识碎片化,不成系统。在面试中,面试者似乎无法完整、清晰地描述自己所开发的系统,或者使用的相关技术。平时可能埋头苦干,或者过于死磕某个实现细节,并没有抬头审视这些技术。

    前人已经掉过的坑,后来的同学就别再“前仆后继”了!

    授人以鱼不如授人以渔,希望大家能通过考点的分析引导,自主思考以找出答案。

    Java基础

    1、谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗?

    考点分析:

    对于这类笼统的问题,你需要尽量表现出自己的思维深入并系统化,Java 知识理解得也比较全面,一定要避免让面试官觉得你是个“知其然不知其所以然”的人。毕竟明白基本组成和机制,是日常工作中进行问题诊断或者性能调优等很多事情的基础,相信没有招聘方会不喜欢“热爱学习和思考”的面试者。

    回归正题,对于 Java 平台的理解,可以从很多方面简明扼要地谈一下,例如:Java 语言特性,包括泛型、Lambda 等语言特性;基础类库,包括集合、IO/NIO、网络、并发、安全等基础类库。对于我们日常工作应用较多的类库,面试前可以系统化总结一下,有助于临场发挥。

    2、请对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别?

    考点分析:

    分析 Exception 和 Error 的区别,是从概念角度考察了 Java 处理机制。总的来说,还处于理解的层面,面试者只要阐述清楚就好了。

    我们在日常编程中,如何处理好异常是比较考验功底的,我觉得需要掌握两个方面。

    第一,理解 Throwable、Exception、Error 的设计和分类。比如,掌握那些应用最为广泛的子类,以及如何自定义异常等。

    很多面试官会进一步追问一些细节,比如,你了解哪些 Error、Exception 或者 RuntimeException?

    第二,理解 Java 语言中操作 Throwable 的元素和实践。掌握最基本的语法是必须的,如 try-catch-finally 块,throw、throws 关键字等。与此同时,也要懂得如何处理典型场景。

    3、谈谈 Java 反射机制,动态代理是基于什么原理?

    考点分析:

    这个题目给我的第一印象是稍微有点诱导的嫌疑,可能会下意识地以为动态代理就是利用反射机制实现的,这么说也不算错但稍微有些不全面。功能才是目的,实现的方法有很多。

    总的来说,这道题目考察的是 Java 语言的另外一种基础机制: 反射,它就像是一种魔法,引入运行时自省能力,赋予了 Java 语言令人意外的活力,通过运行时操作元数据或对象,Java 可以灵活地操作运行时才能确定的信息。而动态代理,则是延伸出来的一种广泛应用于产品开发中的技术,很多繁琐的重复编程,都可以被动态代理机制优雅地解决。

    从考察知识点的角度,这道题涉及的知识点比较庞杂,所以面试官能够扩展或者深挖的内容非常多,比如:

    考察你对反射机制的了解和掌握程度。

    动态代理解决了什么问题,在你业务系统中的应用场景是什么?

    JDK 动态代理在设计和实现上与 cglib 等方式有什么不同,进而如何取舍?

    4、Java 提供了哪些 IO 方式? NIO 如何实现多路复用?

    在实际面试中,从传统 IO 到 NIO、NIO 2,其中有很多地方可以扩展开来,考察点涉及方方面面,比如:

    基础 API 功能与设计, InputStream/OutputStream 和 Reader/Writer 的关系和区别。

    NIO、NIO 2 的基本组成。

    给定场景,分别用不同模型实现,分析 BIO、NIO 等模式的设计和实现原理。

    NIO 提供的高性能数据操作方式是基于什么原理,如何使用?

    或者,从开发者的角度来看,你觉得 NIO 自身实现存在哪些问题?有什么改进的想法吗?

    5、如何保证容器是线程安全的?ConcurrentHashMap 如何实现高效地线程安全?

    典型回答:

    Java 提供了不同层面的线程安全支持。在传统集合框架内部,除了 Hashtable 等同步容器,还提供了所谓的同步包装器(Synchronized Wrapper),我们可以调用 Collections 工具类提供的包装方法,来获取一个同步的包装容器(如 Collections.synchronizedMap),但是它们都是利用非常粗粒度的同步方式,在高并发情况下,性能比较低下。

    另外,更加普遍的选择是利用并发包提供的线程安全容器类,它提供了:

    各种并发容器,比如 ConcurrentHashMap、CopyOnWriteArrayList。

    各种线程安全队列(Queue/Deque),如 ArrayBlockingQueue、SynchronousQueue。

    各种有序容器的线程安全版本等。

    具体保证线程安全的方式,包括有从简单的 synchronize 方式,到基于更加精细化的,比如基于分离锁实现的 ConcurrentHashMap 等并发实现等。具体选择要看开发的场景需求,总体来说,并发包内提供的容器通用场景,远优于早期的简单同步实现。

    6、谈谈接口和抽象类有什么区别?

    考点分析:

    这是个非常高频的 Java 面向对象基础问题,看起来非常简单的问题,如果面试官稍微深入一些,你会发现很多有意思的地方,可以从不同角度全面地考察你对基本机制的理解和掌握。

    比如:

    对于 Java 的基本元素的语法是否理解准确。能否定义出语法基本正确的接口、抽象类或者相关继承实现,涉及重载(Overload)、重写(Override)更是有各种不同的题目。

    在软件设计开发中妥善地使用接口和抽象类。你至少知道典型应用场景,掌握基础类库重要接口的使用;掌握设计方法,能够在 review 代码的时候看出明显的不利于未来维护的设计。

    掌握 Java 语言特性演进。现在非常多的框架已经是基于 Java 8,并逐渐支持更新版本,掌握相关语法,理解设计目的是很有必要的。

    Java进阶

    7、synchronized 底层如何实现?什么是锁的升级、降级?

    考点分析:

    今天的问题主要是考察你对 Java 内置锁实现的掌握,也是并发的经典题目。我在前面给出的典型回答,涵盖了一些基本概念。如果基础不牢,有些概念理解起来就比较晦涩,我建议还是尽量理解和掌握,即使有不懂的也不用担心,在后续学习中还会逐步加深认识。

    我个人认为,能够基础性地理解这些概念和机制,其实对于大多数并发编程已经足够了,毕竟大部分工程师未必会进行更底层、更基础的研发,很多时候解决的是知道与否,真正的提高还要靠实践踩坑。

    后面我会进一步分析:

    从源码层面,稍微展开一些 synchronized 的底层实现,并补充一些上面答案中欠缺的细节,有同学反馈这部分容易被问到。如果你对 Java 底层源码有兴趣,但还没有找到入手点,这里可以成为一个切入点。

    理解并发包中 java.util.concurrent.lock 提供的其他锁实现,毕竟 Java 可不是只有 ReentrantLock 一种显式的锁类型,我会结合代码分析其使用。

    8、synchronized 和 ReentrantLock 有什么区别?有人说 synchronized 最慢,这话靠谱吗?

    考点分析:

    今天的题目是考察并发编程的常见基础题,我给出的典型回答算是一个相对全面的总结。

    对于并发编程,不同公司或者面试官面试风格也不一样,有个别大厂喜欢一直追问你相关机制的扩展或者底层,有的喜欢从实用角度出发,所以你在准备并发编程方面需要一定的耐心。

    我认为,锁作为并发的基础工具之一,你至少需要掌握:

    理解什么是线程安全。

    synchronized、ReentrantLock 等机制的基本使用与案例。

    更近一步,你还需要:

    掌握 synchronized、ReentrantLock 底层实现;理解锁膨胀、降级;理解偏斜锁、自旋锁、轻量级锁、重量级锁等概念。

    掌握并发包中 java.util.concurrent.lock 各种不同实现和案例分析。

    典型回答:

    synchronized 是 Java 内建的同步机制,所以也有人称其为 Intrinsic Locking,它提供了互斥的语义和可见性,当一个线程已经获取当前锁时,其他试图获取的线程只能等待或者阻塞在那里。

    在 Java 5 以前,synchronized 是仅有的同步手段,在代码中, synchronized 可以用来修饰方法,也可以使用在特定的代码块儿上,本质上 synchronized 方法等同于把方法全部语句用 synchronized 块包起来。

    ReentrantLock,通常翻译为再入锁,是 Java 5 提供的锁实现,它的语义和 synchronized 基本相同。再入锁通过代码直接调用 lock() 方法获取,代码书写也更加灵活。与此同时,ReentrantLock 提供了很多实用的方法,能够实现很多 synchronized 无法做到的细节控制,比如可以控制 fairness,也就是公平性,或者利用定义条件等。但是,编码中也需要注意,必须要明确调用 unlock() 方法释放,不然就会一直持有该锁。

    synchronized 和 ReentrantLock 的性能不能一概而论,早期版本 synchronized 在很多场景下性能相差较大,在后续版本进行了较多改进,在低竞争场景中表现可能优于 ReentrantLock。

    说到最后给大家免费分享一波福利吧!我自己收集了一些Java资料,里面就包涵了一些BAT面试资料,以及一些 Java 高并发、分布式、微服务、高性能、源码分析、JVM等技术资料

    资料获取方式:请加群BAT架构技术交流群:171662117

    相关文章

      网友评论

        本文标题:面试处处碰壁?教你一招,心仪offer十拿九稳。

        本文链接:https://www.haomeiwen.com/subject/jaepmqtx.html