本文回顾了Java中数组的相关知识,同时探究了可变参数的实现原理。
申明数组
当申明数组时,Java支持以下两种方式
1 | 类型[] 数组名; |
示例:
1 | int[] arr; |
如果熟悉C语言,就会发现:第二种写法与C语言中定义数组的写法没有区别。
在Java中,推荐采用第一种写法,它直观地表明了这是一个数组类型。
使用数组
在使用前,必须为数组分配空间:
1 | // 此时arr中的元素全为0 |
初始化
1 | arr[0] = 1; |
当然,我们也可以在申明数组的同时,对数组进行赋值。
1 | int[] arr = new int[] {1, 2, 3}; |
上面的写法可以进一步精简为:
1 | int[] arr = {1, 2, 3}; |
默认属性
每个数组都有一个length字段,用于记录数组的长度。
1 | int[] arr = {1, 2, 3}; |
该字段是由Java虚拟机自动创建的。在HotSpot虚拟机中,它存储在对象头中。
关于对象头,可以参看《深入理解Java虚拟机:JVM高级特性与最佳实践》第2章中“对象的内存布局”一节。
多维数组
下面以二维数组为例
1 | // 定长的二维数组 |
虽然Java支持多维数组,但在开发中,一般只使用二维数组。这是因为三维(及以上)数组理解起来并不容易。
Arrays工具类
为了方便操作数组,JDK中提供了一个工具类java.util.Arrays,它可以用于对数组进行排序、判断两个数组是否相等等操作。
将数组转变为字符串
如果是一维数组
1 | Arrays.toString(xx[] arr); |
如果是多维数组,可以使用
1 | Arrays.deepToString(Object[] a); |
判断数组是否相等
如果是一维数组
1 | Arrays.equals(xx[] a, xx[] a2); |
如果是多维数组,可以使用
1 | Arrays.deepEquals(Object[] a1, Object[] a2); |
将数组转变为列表
1 | // ...表示可变参数 |
注意:转换得到的列表支持查询和修改操作,但不支持添加和删除操作。
当执行add或者remove方法时,将抛出java.lang.UnsupportedOperationException。
1 | // 这里的ArrayList是Arrays的一个静态内部类,而不是java.util.ArrayList |
java.util.Arrays.ArrayList继承了java.util.AbstractList,但没有重写add和remove方法。
可变参数
在Arrays.asList()中,出现了T… a,这叫做可变参数(Variable arguments,简称Varargs),语法如下:
1 | // 三个点...的左右允许有任意多个空格 |
可变参数可以输入任意多个参数,包括0个。但是,它必须是方法的最后一个参数。
错误的例子
1 | // 无法通过编译 |
实现原理
可变参数本质上就是一个数组,它只是编译器提供的一种语法糖。以下面的代码为例
1 | import java.util.Arrays; |
对Main.class文件进行反编译,得到如下的结果:
1 | import java.util.Arrays; |
可以看到:可变参数在调用的时候变成了一个数组类型的参数。