• ArrayList初始化


    ArrayList初始化 - Java那些事儿

    ArrayList部分一共五篇文章了,并且引入了时间复杂度来分析,强烈建议大家一定要按顺序阅读,本文是第1篇。

    前些天的文章,反复的画图,不停的重复,就是想让大家理解,对象在内存中是什么样的。也是为今天的及以后的讲解打下基础。如果要说大家在写Java代码的时候哪个类用得最多,我想除了String,基本上就是ArrayList了吧,那今天我们说说ArrayList。

    首先ArrayList是一个普通的类,我们来看一段代码:

    首先:执行List<Person> list1 = new ArrayList<>();当看到new这个关键字的时候,我们脑袋里应该第一印象就是这货在堆内存开辟了一块空间,好我们再来画一画。

    注:常量池位于方法区,方法区位于堆内存,前面没涉及到,所以没画方法区,现在补上

    好,既然是new出来的,那我们直接从构造函数入手,看一下构造函数做了什么。

    很简单,就一行代码,继续看一下,this.elementData和DEFAULTCAPACITY_EMPTY_ELEMENTDATA分别是什么

    红框里的内容是不是似曾相识?是的,和String一样,底层是数组,唯一的区别是String底层是char[]数组(忘了的可以复习一下,传送门:String是一个很普通的类 - Java那些事儿),而这儿是Object[]数组,也就是说该数组可以放任何对象(所有对象都继承自父类Object),执行完构造函数后,如下图。

    注:static修饰的变量,常驻于方法区,我们不需要new,JVM会提前给我们初始化好,这个特性在实际开发过程中,经常拿来做缓存。在让人疑惑的Java代码 - Java那些事儿 一文中,我们文中Integer的缓存就是最好的例子。static变量又叫类变量,不管该类有多少个对象,static的变量只有一份,独一无二。
    fianl修饰的变量,JVM也会提前给我们初始化好。
    transient这个关键字告诉我们该对象在序列化的时候请忽略这个元素,后续我们会讲序列化,这儿先跳过。

    继续执行:List<Person> list2 = new ArrayList<>();

    ArrayList这个类的作者真是好贴心,new的时候连缓存都考虑到了,为了避免我们反复的创建无用数组,所有新new出来的ArrayList底层数组都指向缓存在方法区里的Object[]数组。

    继续执行Person person1 = new Person("张三")

    继续,执行list1.add(person1),不多说,看源码ArrayList是怎么处理add的。

    我们先看ensureCapacityInternal方法,方法里有个参数是size,看们先看一下这个size从哪来的。

    原来是一个成员变量,相信大家看到size一猜就知道大概是干嘛的了吧。好,我们在图里的ArrayList对象里补上它,size是int基本数据类型,成员变量初始化的为0。

    继续往下看

    ensureCapacityInternal方法是在add里面调用的。

    再看grow方法

    跟进到Arrays这个工具类,很简单

    再看copyOf()方法

    最后我们来看一下System.arraycopy()方法,好奇怪,这个方法只有定义,却没有实现,方法用了一个native来修饰。native的方法,是由其它语言来实现的,一般是(C或C++),所以这儿没有实现代码。这是一个数组拷贝方法,大家还在写for循环拷贝数组吗?以后多用这个方法吧,简单又方便还能获得得更好的性能。

    注:native方法,我们会后续会讲解,我们先关注本章内容。

    由于数组内容目前为空,相当于没有拷贝。折腾了这么久,原来只是为了创建一个默认长度为10的Object[]数组,有些朋友说,直接new不就行了,这么费劲,其实这里面大有文章,别急,稍后会说,继续画图。

    再回过头来看,add()这个方法,继续往下执行:

    很简单,size现在是0,就是把传进来的这个e(这里是person1),放到list1的elementData[]下标为0的数组里面,同时size加1,老规矩,上图。

    注意看红框里,虽然我们list1里的elementData数组的长度是10,但是size是1,size是逻辑长度,并不是数组长度。

    现在debug一下,验证我们图里的内容:

    好的,执行一下本文开始那段代码,看结果:

    顺便看一看size()方法的源码:

    有人说,呀,就一个元素,在堆内存中占了10个位置,好浪费呀,没办法,你要享受ArrayList的便利与丰富的API,就得牺牲一下空间作为代价。

    注:本专栏文章首发于公众号:saysayJava。所有示例代码均已上传至公众号,需要请关注下载。

    如果喜欢本系列文章,请为我点赞或顺手分享,您的支持是我继续下去的动力,您也可以在评论区留言想了解的内容,有机会本专栏会做讲解,最后别忘了关注一下我。

    转载无限欢迎,但请注明「作者」和「原文地址」。转载请在文中保留此段,感谢您对作者版权的尊重。如需商业转载或刊登,请联系作者获得授权。

  • 相关阅读:
    java swing学习
    JCheckBox相关知识点
    【python 第五日】 函数闭包与装饰器
    【python第四日】 文件处理 生成器 迭代器
    【Python3 第三日】%和format格式化输出 函数
    【python第二日】运算符 数据类型(数字 字符串 列表 元组 字典 集合) 重新定义比较大小
    怎么设置博客园样式
    【python】第一日 python2和python3区别 命名方式 三种结构
    mybatis-generator.xml
    SpringBoot集成mybatis和mybatis generator
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/14062589.html
Copyright © 2020-2023  润新知