数组:一个长度固定,并且其中数据类型相同的容器
最简单的数组声明方法
数据类型[] 数组名 = new 数据类型[容量];
数据类型[] 数组名 = {数组元素1,数组元素2,数组元素3};
数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[]{数组元素1,数组元素2,数组元素3};
三种声明方法,第一种用于定长数组,第二第三种不但定长,而且能确定数组中的元素
重点在于了解数组的存储方式和特性,这样能让我们在之后的使用中更准确
数组的存储方式
我们要知道程序员new 出一个数组是向jvm(java虚拟机)的堆区申请一块地址连续的空间,我们声明的数组名是存在jvm的栈中的,而数组名所存储的是堆区中连续空间的首地址
什么是首地址,废话不多说直接上图
![](https://i-blog.csdnimg.cn/blog_migrate/d1f7d6dd8cbab15fddd9bb0933fbb50a.png)
即数组在堆区的第一个元素的地址
在数组中,我们看到了堆区和栈的连接方式就是通过首地址,现在有一个问题
我给出一段代码
/*
数组容量为 10 ,存储数据类型为 int 类型的数组
*/
int[] arr = new int[10];
arr[5] = 10;
int[] arr2 = new int[10];
arr2[2] = 100;
// 数组名是一个引用数据类型变量,可以进行赋值操作,赋值内容是【地址】
arr = arr2;
arr2[2] = 200;
arr[5] = 100;
System.out.println(arr[5]);
System.out.println(arr[2]);
System.out.println("-----------------------------");
System.out.println(arr2[2]);
System.out.println(arr2[5]);
这里可以思考一下arr[5], arr[2], arr2[2], arr2[5] 分别是多少?
输出结果如下:
100
200
-----------------------------
200
100
是不是和你想的不太一样,这里我们容易被迷惑的点是这一行代码
// 数组名是一个引用数据类型变量,可以进行赋值操作,赋值内容是【地址】
arr = arr2;
这里数组之间进行赋值操作之间传递的内容是数组的首地址,这里数组arr2的首地址赋值给了arr,这时arr中存储的就是原来arr2的首地址,换句话说,当赋值完成时,arr和arr2指向的是堆区中同一块区域
![](https://i-blog.csdnimg.cn/blog_migrate/ba016f3a6ed7d9ee27ac3d1c389af825.png)
![](https://i-blog.csdnimg.cn/blog_migrate/fb398558163555bebb6d2228746b53b1.png)
这时我们再来看代码
// 数组名是一个引用数据类型变量,可以进行赋值操作,赋值内容是【地址】
arr = arr2;
arr2[2] = 200;
arr[5] = 100;
这时操作arr数组就相当于操作arr2
![](https://i-blog.csdnimg.cn/blog_migrate/19a108bf6247ca3e6f154065370da09a.png)
在这里我们就要区分arr和arr[i]的区别了,arr就是一个数组,指向的是一个地址值,arr[i]是一个数组中对应下标为i的元素,是一个值,这个点是我在学习数组初期经常搞不清楚的问题。
数组扩容问题
在java中,数组的长度总是固定的,但是我们遇到的实际问题,会导致数组元素溢出,比如说我们要在一个满元素的数组中插入一个元素,这将会导致出现错误,这时就要用到数组的扩容。由于原先的数组定长,我们需要在堆空间中重新开辟一片更大空间,将原先数组的元素复制进去,再进行操作。入股这时我们之前申请的空间现在并没有被引用,这时java的gc(垃圾回收机制)会进行判断,这块空间是否还在被引用,之后是否还有引用,不定时间之后,gc会进行回收,这里简单提一下gc,之后的文章详细讲解一下。
干货时间
讲了这么多,我想知道数组在用的时候到底要注意什么呢?
在使用数组时,我们要先清楚的知道,我们要操作的是数组的地址还是要操作数组内的元素
一般我们在进行扩容的时候会去操作地址,而在做数据的插入,删除和查询时操作的都是元素。
时刻注意数组下标,数组下标都是从0开始到arr.length-1结束
//声明一个长度为5的数组
int[] arr = {3,8,2,4,9};
//输出数组第一个元素
System.out.println(arr[0]);
//输出数组最后一个元素
System.out.println(arr[arr.length - 1]);
结果为:
3
9
当你的元素个数超出数组长度,这时候就需要扩容了
3.数组的范围最大是多少?
其实,数组的范围取决于下标的范围,由于下标是int值,int的取值范围为 -2^31~2^31-1。数组的范围为 0~2^31-9 即 0到int最大值-8,为什么会是这个范围?
数组的下标并不能取负值,而且数组的最大范围会留有一个字节的余量
4.数据一致性问题
一般来说,我们在写一个方法的时候,获得的参数,从操作开始,包括在操作的过程中,这些参数的类型不建议进行类型转换,可能会出现精度丢失和无法类型转换回去的问题。
//声明一个char类型的数组
float[] arr = {12.5F, 10.2F, 10.8F};
//将float类型的值给一个double类型
double a = arr[0];
//!!!注意,这个时候是不可以的,这里会导致数据类型不一致问题,在java中也是不允许存在的
arr[1] = a;
5.数据的保护问题
现在思考一个问题,如果我在操作数组的时候,不小心删除,或者删除之后后悔了,想要回之前原来的数据怎么办?
这时我们就要有对数据保护的思维,这里有两个方法可以解决这个问题,方法一:可以以通过复制一个数组,对这个新的数组进行操作,在操作完成之前,我们随时都可以反悔,我们的源数据并不会被破坏,这里就是一个事务的思维。方法二:在删除的时候我们将删除的元素返回出来,交给用户,如果用户想恢复,只需要将这个数据再插入进数组即可。
相当于对数据进行了备份,这个思维对于以后的开发也会有所帮助。
如有不足,私信或者评论指正,肥肠感激。🙋