文章目录
数组
一、数组元素的默认初始化值:
- 整型:0
- 浮点型:0.0
- char型:’\u0000’【即 0 对应的那个"空字符",不是 “空格” ,也不是 ‘0’】
- 布尔型:false
- 引用类型:null
二、二维数组
- 其实从Java的数组底层的运行机制来看,没有多维数组【二维数组本身依然只是一个一维数组,只不过每个元素,又都指向了一个一维数组,逻辑上看起来像一个二维数组】
- 二维数组在初始化的时候,第二维可以不指定数值,但是第一维必须指定清楚(就相当于一维数组,要指定清楚;从这里也能看出,二维数组本身其实就是一个一维数组)
//二维数组元素的默认值
public void test(){
int[][] arr6 = new int[3][4];
//注意,这里已经外层、内层数组都指定好了,都开辟好了(不是 new int[3][])
System.out.println(arr6[0]); //地址值 [I@15db9742
/* '['表示是一维的,'I'表示是int型的,'@'后面则是地址值(十六进制表示) */
System.out.println(arr6[0][0]); //0
System.out.println(arr6); //地址值 [[I@6d06d69c
}
三、数组内存解析
3.1、JVM内存结构简析
垃圾回收器:引用计数算法
- 判断堆空间中的某块空间,是否还有栈空间中的引用指过来,如果没有了,说明这块堆空间没办法被别人调用了,说明是垃圾,就会在未来某个不确定的时间(空闲时),由垃圾回收机制(GC)回收
3.2、二维数组内存解析(图例):
简要过程:
-
执行第一条语句:int[][] arr1 = new int[4][];
----> 目前都是在 main() 方法中执行的语句,变量 arr1 是局部变量,存入栈空间;
----> new关键字,在堆空间新开辟一块容量为4的空间(第一个中括号中指定了),首地址假设为 0x1234(十六进制哈希值);
----> 由于是二维数组,第一层每个元素都又是一个一维数组,是引用类型,默认初始值为null;
----> 将首地址 0x1234 赋值给栈空间中的变量 arr1,这样 arr1 就指向了这片堆空间,可以通过 arr1 找到该数组; -
执行第二条语句:arr1[1] = new int[]{1, 2, 3};
----> arr1[1] 本身即是一个一维数组,new关键字,再在堆空间中新开辟一块容量为3的空间(静态初始化,长度给定了),首地址假设为 0x7788;
----> int 型数组,元素默认值为 0,然后立即被覆盖成:1, 2, 3;
----> 将首地址 0x7788 赋值给 arr1[1],从此 arr1[1] 不再是初始值 null,而是一个地址值,指向这块新空间,从而能够通过 arr1[1] 找到具体第二层数组,即真正的 int 型数据元素; -
执行第三条语句:arr1[2] = new int[4];
----> 同上,这里采用的是动态初始化,元素没有给定值,维持默认值; -
执行第四条语句:arr1[2][1] = 30;
----> 将 arr1[2][1] 位置的元素,修改成 30(覆盖初始值);
两个注意点:
- 对于String类型,其元素真正的String字符串并不是放在数组内,而是在常量池中(常量池又在方法区内),数组中存放的是 “指向常量池中该字符串” 的地址值,【这样才能做到统一:引用类型的变量,存的都是地址值,或者null】
- 所谓的地址值(例如,数组首地址),其实并不是真正意义上的硬件地址,而是JVM虚拟出来的哈希值,【相当于屏蔽了底层地址,比C语言的指针简化了】