首先,ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。对于ArrayList而言,它实现List接口、底层使用数组保存所有元素。其操作基本上是对数组的操作。1、程序中报错的 at java.util.ArrayList.elementData(ArrayList.java:400) 和 at java.util.ArrayList.add(ArrayList.java:441),它们同属Add()方法。

添加操作,首先会调用ensureCapacityInternal(size + 1),其作用为保证数组的容量始终够用,其中size是elementData数组中元组的个数,初始为0。

在ensureCapacityInternal()函数中,用if判断,如果数组没有元素,给数组一个默认大小,会选择实例化时的值与默认大小中较大值,然后调用ensureExplicitCapacity()。

函数体中,modCount是数组发生size更改的次数。然后if判断,

如果数组长度小于默认的容量10,则调用扩大数组大小的方法grow()。

函数grow()解释了基于数组的ArrayList是如何扩容的。数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。接下来回到Add()函数,继续执行,elementData[size++] = e; 这行代码就是问题所在,当添加一个元素的时候,它可能会有两步来完成:1. 在 elementData[Size] 的位置存放此元素;2. 增大 Size 的值。在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。那好,我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。这就解释了为何集合中会出现null。但是数组下标越界还不能仅仅依靠这个来解释。我们观察发生越界时的数组下标,分别为10、15、22、33、49和73。结合前面讲的数组自动机制,数组初始长度为10,第一次扩容为15=10+10/2,第二次扩容22=15+15/2,第三次扩容33=22+22/2...以此类推,我们不难发现,越界异常都发生在数组扩容之时。由此给了我想法,我猜想是,由于没有该方法没有同步,导致出现这样一种现象,用第一次异常,即下标为15时的异常举例。当集合中已经添加了14个元素时,一个线程率先进入add()方法,在执行ensureCapacityInternal(size + 1)时,发现还可以添加一个元素,故数组没有扩容,但随后该线程被阻塞在此处。接着另一线程进入add()方法,执行ensureCapacityInternal(size + 1),由于前一个线程并没有添加元素,故size依然为14,依然不需要扩容,所以该线程就开始添加元素,使得size++,变为15,数组已经满了。而刚刚阻塞在elementData[size++] = e;语句之前的线程开始执行,它要在集合中添加第16个元素,而数组容量只有15个,所以就发生了数组下标越界异常!

数组下标越界异常是如何产生的相关推荐

  1. 5.java.lang.IndexOutOfBoundsException(数组下标越界异常)

    5.java.lang.IndexOutOfBoundsException(数组下标越界异常) 参考文章: (1)5.java.lang.IndexOutOfBoundsException(数组下标越 ...

  2. 如何解决数组下标越界异常

    如何解决数组下标越界异常 今天在写接口的时候运行发现有一个数组的下标越界异常了, 检查了一下发现实在上面的数组中有一些字符串没有大写,造成跟下面的数组字符串不一样,所以导致了数组下标越界异常.

  3. ArrayIndexOutOfBoundsException数组下标越界异常的解决过程

    一. 异常示例 对于刚开始学习Java的大部分人来说,在使用数组的过程中,经常会遇到数组下标越界的异常.下面壹哥就以一个实际案例来给大家进行说明: public class ArrayTest {pu ...

  4. 数组下标越界异常解决方法

    数组下标越界异常解决方法 参考文章: (1)数组下标越界异常解决方法 (2)https://www.cnblogs.com/GreenCode/p/7345508.html 备忘一下.

  5. Java初学最容易犯的错,数组下标越界异常怎么解决呢?

    数组下标越界是一个编程初学者最容易犯的错误. 以一个简单的一维数组为例: int a[10]:这是一个整型的数组a,有10个元素:a[0]-a[9],因为正确的下标应该是从0开始,到9结束,与生活习惯 ...

  6. java中数组下标越界的异常_java新手求助 数组下标越界异常

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这是一个输入有n个数字的数组,选出k个最小值的函数. import java.util.*; public class example { public ...

  7. 数组常见异常 学习笔记

    package com.ctgu.java.exer;public class TestException {public static void main(String[] args) {//1.数 ...

  8. java 二维数组_Java中二维数组和异常的内容及应用

    一.二维数组 数组中嵌套数组就是二维数组 二维数组的声明 数据类型[][] 数组名; --推荐 数据类型 数组名[][]; 初始化: 动态: 数据类型[][] 数组名 = new 数据类型[一维的长度 ...

  9. Java实验4-1【数组下标越界异常处理】

    文章目录 前言 一.任务介绍 1.任务描述 2.运行结果 3.任务目标 4.实现思路 二.程序实现 1.代码 2.实验结果(输出结果) 三.总结 前言 一.任务介绍 1.任务描述 编写程序,捕获并处理 ...

最新文章

  1. Python基础教程:type()函数-动态创建类
  2. 十九、面试必考,Java中的this关键字
  3. javaWeb开发总结 ---- 前端数据插入到后台
  4. 【AI视野·今日CV 计算机视觉论文速览 第179期】Tue, 25 Feb 2020
  5. Spring EclipseLink NoSQL - 使用MongoDB和Oracle NoSQL DB构建
  6. A + B Problem II
  7. SQL Server数据类型概述
  8. Scrapy简单入门及实例讲解
  9. Go实现 爬虫v0.2
  10. php算法结构,PHP中常用算法以及数据结构
  11. 深度解析 mPaaS 小程序一站式研发
  12. 合泰单片机驱动步进电机程序
  13. 三阶魔方层先法自动复原_Python
  14. Python打印简单杨辉三角形
  15. 某些老司机直播APP这么受欢迎?作为Android程序员如何进军音视频?
  16. 分析pc计算机的性能方面,《腐烂国度2》PC性能表现分析 中档电脑轻松驾驭
  17. linux中测端口通讯nc,linux命令之 - nc 测试端口的连通
  18. Android辅助功能
  19. 深度学习之upsampling downsampling
  20. 计算机中丢失IDAP,certify_ldap.dll

热门文章

  1. android 文件管理器下载,ES文件管理器下载
  2. 如何搭建动态IP池?手把手教你3种方法!
  3. 赵栋 201771010137 《面向对象程序设计(java)》课程进度表
  4. SPI控制MS5614T
  5. 命令行中运行jar包(cmd)
  6. 如何进阶优秀数据分析师行列?方法、技术与工具,缺一不可!
  7. 典型计算机电路组成,硬件工程师必会的几道题
  8. Linux系统中的超级用户,普通用户,特殊用户(特殊用户)3种类型
  9. 《C++primer》第10章:泛型算法
  10. 其次线性方程组,行列式为0,一定有非0解.