当前位置: 首页 > 后端技术 > Java

JDK成长笔记1:我的天!学完这个成长故事,面试100次Java基础都不用愁了!

时间:2023-04-01 19:27:22 Java

为了让工程师更好的提升个人技术能力和思维,我会开一个大专栏《成长记》系列,里面会包括Java架构和大数据从底层技术到源码原理的分享,所以留调整!无论你是Java程序员还是大数据工程师,工作时间长了,很多底层、基础的技术可能都还给了你的大学老师,或者80%都被抛在脑后了。例如,你可能不记得网络模型有多少层?你可能分不清TCP三次握手和四次挥手的过程?你可能根本没看过JDK集合和并发包的源码,或者很久以前看过,只是不记得了。连concurrent包下的很多东西都没用过。你也可能正在准备跳槽或面试,被各种基金会虐过,或者看到某个技术框架的源码难懂,无从下手……更多或多或少你可能遇到过这样的场景,那么在这个《成长笔记》系列中,就是为你解决这些问题。我不仅会教你学习这些底层和基础知识,还会解决上面的问题。《成长笔记》更重要的核心是:带给你的除了能力、知识、方法的成长,更重要的是观念和心态的成长。所以你可以在每个栏目中学到很多概念和思路,潜移默化地提高你的认知,让你不仅得到“鱼”,还得到“鱼”。作为《成长记》的第一篇专栏,《JDK成长记》这一期专栏主要让你掌握以下三点:JDK源码中各种类型的集合和并发包的底层原理,你就不会再心虚了当你在跳槽面试中遇到这些知识时。在使用JDK集合和并发的时候,可以更加得心应手,可以更好的解决线上遇到的各种问题。更重要的是让你学会阅读源码的基本思路。作为程序员,我们实际上构建了整个社会计算机技术的底层系统。但是,除此之外,你还得建立自己想法的底层系统。这个底层系统不仅会帮助你提升技术能力和职业发展,还会帮助你的生活乃至整个人生变得更好。而且每个人的底层系统都不一样,所以需要不断的修改和巩固。这是《成长记》给你的另一种成长。关注《成长记》的各个栏目,相信你学到的不仅仅是知识和技能,还有更多的思想和观念。好了,接下来,就让我们进入JDK源码的大门吧!作为Java工程师,ArrayList应该很熟悉了。作为一名菜鸟Java工程师,在面试的时候可能经常会被问到:能不能说说ArrayList的基本原理和优缺点?它的默认容量是多少?如何扩展它?诸如此类,不知道你当初是怎么回答的。又或许你已经是一名资深工程师,是否经常忘记设置ArrayList的容量?或者你是老手,可能要跳槽了,一起来温习一下ArrayList的基础知识吧!ArrayList的基本原理总之,在JDK中,ArrayList的底层是基于一个Object[]数组来维护数据的。ArrayList的优缺点缺点:当容量有限时,数组需要扩容,元素复制会影响性能。中间频繁的删除和插入元素会造成元素移动和元素复制,影响性能。某种元素具有良好的性能。建议:维护顺序插入的数据,很方便遍历或者索引访问,预估数据大小,避免频繁扩容。不适合频繁删除中间插入和多线程操作等操作。复习完ArrayList的基本原理和优缺点后,最好饭后找人聊聊,把这个问题问他,或者跟他说说,巩固一下这个基础知识。接下来就可以开始看ArrayList的源码了。在看之前,首先要了解阅读源码最基本的思路。当你打开源代码时,你绝对不会从头开始阅读它。这会让你一头雾水,所以一定要有思路和方法去寻找。在这里,首先要明白,看核心源码的方式和精读源码是不一样的。看核心源码,也就是核心部分的源码,一般是10-30%。应该从一些入口入手,但是如果想要精读源码,除了阅读核心源码之外,还需要对源码进行反汇编,研究各个组件的功能,然后再从入口入手,逐行阅读。这其实体现了一个很重要的思想,不管做什么,先摸一下脉络再看细节。就好比瞎子摸大象。每一个部分你都摸到,却没有一个整体的认识,这很滑稽。所以一般应该先看核心源码,再精读源码。除了以上思路,阅读源码其实还有很多技巧和方法。不同的人有不同的看法。相信你会在这个成长故事中学到很多东西。但是我要告诉大家的一点是,大家可能在网上看到有很多diss的看源码的方式,那种看源码的方式,还有各种博客和论坛看源码以各种方式编码。所以很多时候,必须要透过现象看本质。其实看源码没有好坏之分。这取决于您的目标和场景。最好的方法是选择正确的方法。想一想,很多事情不都是这样的吗?大家不能一概而论,这个思路很重要,你要学会站在一定的高度看问题,不要总是陷在问题本身。根据我的经验和学习到的各种阅读源码的方法,你可以在本章最后看到一个总结。看源码前,如前所述,先看上下文,再看细节。比如看ArrayList的源码,首先可以看到它有哪些核心成员变量。一开始你肯定不知道哪些是核心变量,简单过一遍就可以了。根据名称和类型,你可以大致看一下,看不懂也没关系。然后看看都有哪些方法,根据名字猜猜它们是干什么的。做这些主要是让你了解基本的脉络,对源码有个大概的印象。不要在这里研究源代码。在Intellij或者Eclipse下,如果使用eclipse快捷键,通过Ctrl+O可以看到这个类的大概情况:这里主要有哪些方法,成员变量,内部类。比如你可以看到在ArrayList的源码中,有几个静态成员,从名字上看好像和容量有关,还有size、elementData等成员变量,几个构造函数,还有一些私有方法比如至于ensureCapacity和calculateCapacity,感觉也跟容量的大小有关。因为Capacity意味着容量和大小。还有很多方法你应该常用add()、set()、get()等。最后,在下面,还有SubList、Itr、ListItr等几个内部类,如下图所示:嗯,其实看到这里,至少你对ArrayList的源码有了一个大概的了解,这个是首先是上下文。细思极恐。我们之前说过,看核心源码一般都是从入口开始,也就是常说的自上而下。首先你需要一个代码演示。从它的入口点开始,代码列表如下:importjava.util.List;公共类ArrayListDemo{publicstaticvoidmain(String[]args){Listlist=newArrayList<>();}}这是一段很简单的代码,入口是main函数,第一行是创建一个ArrayList,里面的元素都是String类型,使用默认的无参数构造函数,你点击构造函数,进入源码看到:privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};transientObject[]elementData;privateintsize;publicArrayList(){this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}可以看出有一个Object[]数组有一个成员变量叫elementData,印证了我们之前说的ArrayList的底层基本原理是数组。还有你还记得在查看ArrayList的源代码上下文时看到过这个变量吗?默认的无参数构造函数使elementData指向与空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA相同的地址。有印象的话,DEFAULTCAPACITY_EMPTY_ELEMENTDATA这个变量也是你之前见过的静态成员变量。上面还列出了一个成员变量size,你也可以猜到,应该是一个描述数组大小的变量。而size是一个int类型,大家都知道int的默认值是0。所以总结一下,你知道newArrayList<>()这个动作在底层使用了一个Object[]数组,但是这个数组是空的默认大小为0。上面我们主要看的是一个简单的源码,看上下文猜测再简单不过了。不知道你有没有感受到这两种想法。有了初步的感觉。接下来介绍一个非常关键的方法:绘图。其实在我看来,没有什么算法是画图和例子看不懂的。至少大部分算法都能看懂。微信小灰算法插画公众号就是最好的例子。阅读源代码时也是如此。画图可以更好的理解源码,让我们站在高处,从高处揣摩源码的脉络。也可以梳理主要思路,让我们更好的阅读源码。所以不能忽视,不管场景多么简单,都要养成画图的习惯。上面ArrayList的无参构造函数的源码基本如下图所示:好了,今天的知识就分享到这里。下一节我们将基本使用ArrayList,调用它的几个常用方法,然后看看它的源码和常用方法的原理。前几季我会尽量放慢节奏,别着急,以后会越来越精彩的!继续看彩蛋~首先说说源码的获取。一般将下载的源码有以下几种导入Intellij等IDE中读取代码。开启Maven自动下载源码功能。从官方(如Github)或Maven仓库手动下载源码。每个都可以拿到源码,每个都有自己的应用场景。比如你要写一些注释,需要导入到IDE中。例如,如果要调试源代码,则不需要将源代码导入IDE。2,3都适用任何方法都可以。又比如有些代码在Maven仓库中根本找不到,只能从Github或者官网下载。其次,说说读静态源码还是动态源码?这个要看源码的复杂程度,你阅读源码的能力等等,如果是一些简单的源码或者你有很多阅读源码的经验,一般阅读静态源码就够了。但是如果你是新手,或者真正的源码比较复杂,或者在执行过程中需要查看某个变量和返回值,那么阅读动态源码肯定需要debug。阅读源码的技巧,说白了就是一些思路。常见的有:自上而下或自下而上的抓大放小,先是脉络,再是细节。:看注释,加注释,画Debug观察日志或者加日志……上面我带你去用,你在合适的场景下学习使用。你只需要继续关注成长笔记即可。最后再说一句,有人说阅读源码需要很多技术基础,确实是这样。但是也分什么样的源码,如果只是简单的源码,需要的基础知识会很少,比如JDK的源码。但如果源码比较难,比如Zookeeper、HDFS、Kafka、Dubbo等,需要掌握Netty、NIO、网络、Java集合和并发等基础知识才能看得更清楚。当然,如果你没有这些基础,你是看不下去的,但是你的理解可能并不深入,最后可能对源码只有一个初步的了解。再次重申,不要一概而论。本文由博客多发平台OpenWrite发布!