Java数组内存解析

图片均来自尚硅谷课件。

1.一维数组内存解析

 

 

 上图给出java程序执行时的内存分配。图中有栈,堆,方法区,各区域分别存储的数据有:

  • 栈:保存局部变量;
  • 堆:保存new出的对象
  • 方法区
    • 常量池:字符常量,如字符串;
    • 静态域:静态变量

 

 上图中中的语句均是在某个方法中执行,方法中的变量即为局部变量,因此一维整数数组ages和字符串数组names均在栈中保存。

局部变量代表的数组均是new出的对象,所以在堆中保存。

int[] ages = new int[4];
ages[0] = 12;
ages[1] = 23;
ages[2] = 33;

执行上述代码时,局部变量ages入栈,在堆中分配存储四个整数元素的连续空间,并初始化为0。将该连续地址空间的首地址与ages一起保存在栈中。整形数组的初始化方式为动态初始化:数组的初始化和数组元素的赋值分开进行。

当执行赋值语句ages[0] = 12时,根据栈中的首地址在堆中找到该元素所在位置并使用12替换0。

String[] names = new String[]{"赵宇", “张恺”, "江运", "曹林"};
names[1] = "刘昭";

上述代码的执行过程如第一个代码块执行过程一样,只不过是堆中分配的连续内存空间存储的是字符串。初始化字符串数组的方式为静态初始化,数组的初始化与数组元素的赋值操作同时进行。

names = new String[]{"Tom","Jerry"};

在执行第二个代码块之后再执行上述语句时,堆中会另外分配出一块连续的内存空间,保存字符串数组的元素。但是这块连续的内存空间与第二个代码块分配的内存空间是独立的,且此时栈中names对应的地址是新分配的内存空间的首地址(0x9999)。0x8999为首的内存空间此时没有引用,在GC扫描后会被收集。

这里堆中分配的保存字符串数组的地址空间实际上存的不是字符串。后续会纠正,在此只需直观上理解为字符串数组的地址空间即可。

 

2.二维数组内存解析

 

 数组中可以保存基本数据类型和引用数据类型。二维数组中的元素是一维数组,一维数组作为引用数据类型保存在二维数组中。

int[][] arr1 = new int[4][];

执行上述代码时,堆先分配一个连续的地址空间,长度为4,用于保存一维数组的首地址,又因为没有初始化一维数组的长度,故此时为null。再将该连续空间的首地址与局部变量arr1一起保存在栈中。

arr1 = new int[]{1,2,3};

 执行上述代码,静态初始化一个一维数组,堆中分配连续地址空间保存整形一维数组,长度为3,并将该地址空间的首地址0x7788赋给arr[1]。

剩余代码执行与上述分析相同。

以上就是Java一维数组的内存解析,如果不当之处,还请指出。

posted @ 2021-09-08 22:32  凸云  阅读(251)  评论(0)    收藏  举报

谢谢打赏!