1 内存的简化结构
new是面向对象中一种典型的创建对象的方式。
![](https://i-blog.csdnimg.cn/blog_migrate/7ac38e01cce049e11f89cd47722a7882.png)
栈:是一个线性表,主要存放局部变量(方法中定义的变量都叫局部变量,比如main()方法中
方法区:包含常量池、静态域
堆:new出来的结构:对象、数组
2 一维数组的内存解析
int arr=new int[]{1,2,3};
String[] arr1=new String[4];
arr1[1]="刘德华";
arr1[2]="张学友";
arr1=new String[3];
System.out.println(arr1[1]);//null
![](https://i-blog.csdnimg.cn/blog_migrate/3ef7bd4ba4d6903842691b419ad2ec76.png)
line1:将堆空间中3个元素的连续空间的首地址值(用16进制表示)赋给栈空间中的变量arr,然后数组的初始值用1,2,3替换掉。
line2:将堆空间中连续内存空间的首地址值赋给栈空间中的arr1,默认初始化值为null
line3:通过角标的方式调用数组中的指定元素,通过arr1访问地址,找到第二和第三个元素的位置,赋值。
line4:重新创建一个数组,堆空间中重新开辟了一个数组,长度为3,新数组的首地址值赋给arr1,arr1指向新的数组,默认初始化值null。
变量都有作用域。main()方法执行完,main方法中的变量就没用了,arr1,arr就相继出栈,arr1出栈,arr1原本所指向的空间没有指针指向,就会被回收,接着arr出栈,原本arr指向的空间就会被回收。
垃圾回收机制:
引用计数算法,判断一下堆空间中的空间是否有栈空间中的引用指过来。
String[] strs = new String[5];
strs[2] = "Tom";
strs = new String[3];
![](https://i-blog.csdnimg.cn/blog_migrate/243240cf9ffee665eea4d25ce6a85584.png)
真实的"Tom"存在了字符串常量池。
引用数据类型的变量放的不是地址值,就是null值。
3 二维数组的内存解析
int[][] arr1=new int[4][];
arr1[1]=new int[]{1,2,3};
arr1[2]=new int[4];
arr1[2][1]=30;
![](https://i-blog.csdnimg.cn/blog_migrate/10e51d515e0aea44ff47b514e6c60e72.png)
line1:造了一个长度是4的数组,首地址值赋给栈空间中的arr1,每个元素的类型都是int型的一维数组,是引用数据类型,默认初始化值为null。
line2:在堆空间中造了一个长度为3的数组,将其首地址值赋给arr1[1],arr1[1]的值变成地址值,内层数组的元素类型为int型,默认初始化值为0,重新赋值为1,2,3。
line3:在堆空间中造了一个长度为4的数组,将其首地址值赋给arr1[2],arr1[2]的值变成地址值,内层数组的元素类型为int型,默认初始化值为0。
line4:将arr1[2][1]的值重新赋值为30。
ps:地址值不是真实地址,java虚拟机虚拟计算出来的哈希值,屏蔽了底层真实的内存地址