数组-不得不讲的细节

数组:一个长度固定,并且其中数据类型相同的容器

最简单的数组声明方法

数据类型[] 数组名 = new 数据类型[容量];
数据类型[] 数组名 = {数组元素1,数组元素2,数组元素3};
数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[]{数组元素1,数组元素2,数组元素3};

三种声明方法,第一种用于定长数组,第二第三种不但定长,而且能确定数组中的元素

重点在于了解数组的存储方式和特性,这样能让我们在之后的使用中更准确

数组的存储方式

我们要知道程序员new 出一个数组是向jvm(java虚拟机)的堆区申请一块地址连续的空间,我们声明的数组名是存在jvm的栈中的,而数组名所存储的是堆区中连续空间的首地址

什么是首地址,废话不多说直接上图

即数组在堆区的第一个元素的地址

在数组中,我们看到了堆区和栈的连接方式就是通过首地址,现在有一个问题

我给出一段代码

         /*
        数组容量为 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指向的是堆区中同一块区域

这时我们再来看代码

// 数组名是一个引用数据类型变量,可以进行赋值操作,赋值内容是【地址】
        arr = arr2;

        arr2[2] = 200;
        arr[5] = 100;

这时操作arr数组就相当于操作arr2

在这里我们就要区分arr和arr[i]的区别了,arr就是一个数组,指向的是一个地址值,arr[i]是一个数组中对应下标为i的元素,是一个值,这个点是我在学习数组初期经常搞不清楚的问题。

数组扩容问题

在java中,数组的长度总是固定的,但是我们遇到的实际问题,会导致数组元素溢出,比如说我们要在一个满元素的数组中插入一个元素,这将会导致出现错误,这时就要用到数组的扩容。由于原先的数组定长,我们需要在堆空间中重新开辟一片更大空间,将原先数组的元素复制进去,再进行操作。入股这时我们之前申请的空间现在并没有被引用,这时java的gc(垃圾回收机制)会进行判断,这块空间是否还在被引用,之后是否还有引用,不定时间之后,gc会进行回收,这里简单提一下gc,之后的文章详细讲解一下。

干货时间

讲了这么多,我想知道数组在用的时候到底要注意什么呢?

  1. 在使用数组时,我们要先清楚的知道,我们要操作的是数组的地址还是要操作数组内的元素

一般我们在进行扩容的时候会去操作地址,而在做数据的插入,删除和查询时操作的都是元素。

  1. 时刻注意数组下标,数组下标都是从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.数据的保护问题

现在思考一个问题,如果我在操作数组的时候,不小心删除,或者删除之后后悔了,想要回之前原来的数据怎么办?

这时我们就要有对数据保护的思维,这里有两个方法可以解决这个问题,方法一:可以以通过复制一个数组,对这个新的数组进行操作,在操作完成之前,我们随时都可以反悔,我们的源数据并不会被破坏,这里就是一个事务的思维。方法二:在删除的时候我们将删除的元素返回出来,交给用户,如果用户想恢复,只需要将这个数据再插入进数组即可。

相当于对数据进行了备份,这个思维对于以后的开发也会有所帮助。

如有不足,私信或者评论指正,肥肠感激。🙋

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值