目录
一、什么是数组
- 数组是一个容器,它可以存储相同类型的多个元素。
- 数组在内存中是连续分配的一块存储区域,每个元素占据相同大小的空间。
- 数组的长度是固定的,一旦创建后就无法改变。
- 数组可以通过索引访问和修改元素,索引从0开始,最大索引为数组长度减一。
- Java提供了针对数组的一些方法,如获取数组长度、复制数组等。
二、声明数组
String[] Array1 = new String[5];
String[] Array2 = {"a","b","c", "d", "e"};
String[] Array3 = new String[]{"a","b","c","d","e"};
1.数组结构
public static void main(String[] args) {
int[] intArray = { 1, 2, 3, 4, 5 };
String intArrayString = Arrays.toString(intArray);
System.out.println(intArray);
System.out.println(intArrayString);
int[] array = new int[10];
System.out.println("array的父类是:" + array.getClass().getSuperclass());
System.out.println("array的类名是:" + array.getClass().getName());
int[] array_00 = new int[10];
System.out.println("一维数组:" + array_00.getClass().getName());
int[][] array_01 = new int[10][10];
System.out.println("二维数组:" + array_01.getClass().getName());
int[][][] array_02 = new int[10][10][10];
System.out.println("三维数组:" + array_02.getClass().getName());
Integer[] array_03 = new Integer[10];
System.out.println("一维数组:" + array_03.getClass().getName());
Integer[][] array_04 = new Integer[10][10];
System.out.println("二维数组:" + array_04.getClass().getName());
Integer[][] array_d05 = new Integer[10][10];
System.out.println("二维数组:" + array_d05.getClass().getName());
}
############################################
输出
[I@5f8ed237
[1, 2, 3, 4, 5]
array的父类是:class java.lang.Object
array的类名是:[I
一维数组:[I
二维数组:[[I
三维数组:[[[I
一维数组:[Ljava.lang.Integer;
二维数组:[[Ljava.lang.Integer;
二维数组:[[Ljava.lang.Integer;
############################################
非封装类型:className为[I,后面跟数据类型大写字母,但long([J)和boolean([Z)除外;
封装类型:className为[Ljava.lang.Integer,后面跟数据类型全名;
对象类型:className统一为[Ljava.lang.Object;
public static void main(String[] args) {
int[] array = new int[10];
Class clazz = array.getClass();
System.out.println(clazz.getDeclaredFields().length);
System.out.println(clazz.getDeclaredMethods().length);
System.out.println(clazz.getDeclaredConstructors().length);
System.out.println(clazz.getDeclaredAnnotations().length);
System.out.println(clazz.getDeclaredClasses().length);
}
########################################
0
0
0
0
0
从这个运行结果可以看出,我们亲爱的[I没有生命任何成员变量、成员方法、构造函数、Annotation甚至连length成员变量这个都没有,它就是一个彻彻底底的空类。
没有声明length,那么我们array.length时,编译器怎么不会报错呢?确实,数组的length是一个非常特殊的成员变量。我们知道数组继承Object类,但是Object是没有length这个成员变量的。
2.字节码结构
public static void main(String[] args) {
int a[] = new int[2];
int i = a.length;
}
########################################
0 iconst_2 //将int型常量2压入操作数栈
1 newarray 10 (int) //将2弹出操作数栈,作为长度,创建一个元素类型为int, 维度为1的数组,并将数组的引用压入操作数栈
3 astore_1 //将数组的引用从操作数栈中弹出,保存在索引为1的局部变量(即a)中
4 aload_1 //将索引为1的局部变量(即a)压入操作数栈
5 arraylength //从操作数栈弹出数组引用(即a),并获取其长度(JVM负责实现如何获取),并将长度压入操作数栈
6 istore_2 //将数组长度从操作数栈弹出,保存在索引为2的局部变量(即i)中
7 return //main方法返回
所以说是JVM创建数组类,应该就是由newarray这条指令触发的了。
JVM通过arraylength这条指令来实现length方法。
JVM这家伙自个偷偷创建了[I类。JVM不把数组类放到任何包中,也不给他们起个合法的标识符名称,估计是为了避免和JDK、第三方及用户自定义的类发生冲突吧。
再想想,JVM也必须动态生成数组类,因为Java数组类的数量与元素类型、维度(最多255)有关,相当相当多了,是没法预先声明好的。
三、分配空间
声明了数组,只是得到了一个存放数组的变量,并没有为数组元素分配内存空间,不能使用。因此要为数组分配内存空间,这样数组的每一个元素才有一个空间进行存储
四、多维数组
多维数组可以看成是数组里再存数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组;
五、数组常用方法
org.apache.commons.lang.ArrayUtils;