数组的内存解析
内存结构:栈(stack)(局部变量)-瘦高, 堆(heap)(new对象,数组)-矮宽,方法区(常量池,静态域)
放在方法中的变量都叫局部变量(比如main方法)
一维数组的内存解析
首先该图是右上角几行代码执行时,内存的解析图,现解释如下
执行int[] arr = new int[]{1, 2, 3};
这里创建了一个int类型的数组,并赋值为1, 2, 3.
假设0x34ab为首地址的值,把该值存放到栈里,数组的值存放到堆里分别为1, 2, 3.刚new的时候默认值为0, 0 , 0,由于赋值了,故数组里的值变为1, 2, 3.
然后执行第二个语句String[] arr1 = new String[4];
用动态创建数组的方法创建了一个空间为4的字符型数组,默认值为null
同样,首地址放在栈里,根据该首地址即可访问数组内的元素
然后执行arr1[1] = “刘德华”;arr1[2] = “张学友”;
通过这两条语句访问内存中的两个元素并赋值,可以看到第二个元素和第三个元素更改了。
最后执行arr1 = new String[3];重新构建了一个动态数组,相当于把原先的arr1 的首地址值更改,故原先不能访问原先的内容了。此时,arr1数组的内容为默认值null。原先的内存会被清理掉,因为栈里的地址值无法只想到原内存。
二维数组
数组里面包含了另一个数组,这就是二维数组,把一个数组看做元素
嵌套呗
二维数组的使用
初始化:
//静态初始化
int[][] arr1 = new int[][]{{1, 2, 3}, {4, 5}, {4,5, 6}};
//动态初始化,3行2列。不定义2也可以的
String[][] arr2 = new String[3][2];
String[][] arr3 = new String[3][];
// 不能不定义行数,只定义列数,也不能都不定义。要么行列都定义,要么可以不定义列数
这是二维数组的静态初始化和动态初始化方法,和一维的一样。把二维数组看成矩阵会更好的理解。
只不过二维数组可以只定义一个行数,而不定义列
获取二维数组的长度
// 获取某一行的长度,相当于求某一行有多少列(也相当于子数组有多少个元素)
System.out.println(arr1[0].length);
// 获取二维数组的行数
System.out.println(arr1.length);
第一行代码获取的是某一行有多少列,可以看做是某一行有多少元素;第二行代码获取的是二维数组的行数,因为对于二维数组,一行就相当于一个元素。(注意广义化的使用)
二维数组的遍历
// 对二维数组进行遍历
for(int i = 0; i < arr1.length;i++){
for(int j = 0;j < arr1[i].length;j++){
System.out.println(arr1[i][j]);
}
System.out.println();
}
// 二维数组使用。外层元素arr[0],内层元素[0][0]。
int[][] array = new int[4][3];
//输出为[I@7ea987ac,代表的是一个地址值,在一位数组的内存解析中讲到过
//一位数组存放的就是地址值,通过该地址值可以访问存放在堆里的元素
System.out.println(array[0]);
//二维数组存放的是二维的地址值[[I@12a3a380,区别是 [ 的个数;这里的 I 代表的是int类型
System.out.println(array);
//外层元素的初始值为:地址值
//内层元素的初始值为:与一位数组初始化情况相同
二维数组的内存解析
首先开辟一个高度为4 的数组(行数为4),地址值存放在栈中。之后在第二行开辟三个元素{1, 2, 3};之后对第三行开辟一个空间,可以容纳四个元素(默认值为0,因为是int型);最后把第二行第一列的元素赋值为30.