Java基础——数组内存简析

数组

一、数组元素的默认初始化值:

  • 整型:0
  • 浮点型:0.0
  • char型:’\u0000’【即 0 对应的那个"空字符",不是 “空格” ,也不是 ‘0’】
  • 布尔型:false
  • 引用类型:null

二、二维数组

  1. 其实从Java的数组底层的运行机制来看,没有多维数组【二维数组本身依然只是一个一维数组,只不过每个元素,又都指向了一个一维数组,逻辑上看起来像一个二维数组】
  2. 二维数组在初始化的时候,第二维可以不指定数值,但是第一维必须指定清楚(就相当于一维数组,要指定清楚;从这里也能看出,二维数组本身其实就是一个一维数组)
//二维数组元素的默认值
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、二维数组内存解析(图例):

在这里插入图片描述

简要过程:

  1. 执行第一条语句:int[][] arr1 = new int[4][];
    ----> 目前都是在 main() 方法中执行的语句,变量 arr1 是局部变量,存入栈空间;
    ----> new关键字,在堆空间新开辟一块容量为4的空间(第一个中括号中指定了),首地址假设为 0x1234(十六进制哈希值);
    ----> 由于是二维数组,第一层每个元素都又是一个一维数组,是引用类型,默认初始值为null;
    ----> 将首地址 0x1234 赋值给栈空间中的变量 arr1,这样 arr1 就指向了这片堆空间,可以通过 arr1 找到该数组;

  2. 执行第二条语句: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 型数据元素;

  3. 执行第三条语句:arr1[2] = new int[4];
    ----> 同上,这里采用的是动态初始化,元素没有给定值,维持默认值;

  4. 执行第四条语句:arr1[2][1] = 30;
    ----> 将 arr1[2][1] 位置的元素,修改成 30(覆盖初始值);

两个注意点:

  1. 对于String类型,其元素真正的String字符串并不是放在数组内,而是在常量池中(常量池又在方法区内),数组中存放的是 “指向常量池中该字符串” 的地址值,【这样才能做到统一:引用类型的变量,存的都是地址值,或者null】
  2. 所谓的地址值(例如,数组首地址),其实并不是真正意义上的硬件地址,而是JVM虚拟出来的哈希值,【相当于屏蔽了底层地址,比C语言的指针简化了】

> 注意:数组一旦初始化,其长度就确定下来,而且不可修改

猜你喜欢

转载自blog.csdn.net/wszhbl/article/details/89602743