栈:方法运行时使用的内存,比如main方法运行,进入方法栈中执行
堆:存储对象或数组,new来创建,都存在对内存中
- 方法区:存储可以运行的class文件
- 本地方法栈:JVM在使用操作系统功能的时候使用,和我们开发无关
- 寄存器:给CPU使用,和我们开发无关
- 程序的主入口(main方法)开始执行时会进入栈,代码执行完毕会出栈
- new出来的东西在堆内存中开辟一块空间,并产生地址
![]()
3. 每new出一个对象或者数组,他们的内存地址是不同的
有如下代码,看一下内存分配:
public static void main(String[] args) {
int a= 10;
int b =10;
int c = a+b;
sout(c)
}
在这个代码中,因为没有new关键字,所以只有栈内存,没有堆内存
首先程序运行时,main方法进入栈内存,从上往下依次运行。
- 首先在栈内存中定义了一个变量a,并开辟了一小块空间给a,给这个变量做了限定,只能存储int类型的数据,再将数值10放入这个空间中,如此,变量a就定义好了
- 以此类推,再在栈内存中开辟一个空间,给这个空间命名为b,同样做了限定,只能存放int类型的数据,再将数值10放入这个空间
- 同样的再开辟一个空间,命名为c。首先将变量a和变量b里面存放的值拿出来相加得20,再存入c空间中(也就是赋值给c)
- sout(c),就是先找到变量c里存储的值,再将c中存储的值打印出来,并打印在控制台中
java中数组的内存分配
如下代码:
package com.wy.csdn;
public class TestArray {
public static void main(String[] args) {
int arr[] = new int[2];
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
arr[0] = 11;
arr[1] = 22;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println("====================");
int[] arr2= {33,44,55};
System.out.println(arr2);
System.out.println(arr2[0]);
System.out.println(arr2[1]);
System.out.println(arr2[2]);
}
}
首先还是main方法进入到栈内存中,依次从上到下执行,不过此时有new对象,所以要考虑堆内存。
- 首先分析等号的左边,int arr[ ] 是放在栈内存中的,其次看等号的右边,也就是 new int[2] 此时是放在堆内存中的,也就是在堆内存中开辟了一个空间,因为数组长度为2,所以会有0,1两个索引,因为是数组为int类型,所以数组的默认值为0.
在堆内存中的开辟的空间是有地址值的,会通过等号运算符,将地址值赋值给等号左边的数组 System.out.println(arr);此时就是将堆内存赋值给栈内存的地址进行打印 System.out.println(arr[0]);首先就是通过数组名arr找到右边堆内存的这个空间,再通过索引[0]找到在堆内存中存放的数据,并再控制台打印。System.out.println(arr[1]);也是相同的,也是通过数组名找到右边堆内存的空间,通过索引arr[1]找到堆内存中存放的数据,并打印。 arr[0] = 11;就是将11赋值给数组arr中0的索引。运行原理就是,先找到堆内存中命名为arr的空间,将11赋值给0索引。0索引原理的元素就被11给覆盖。同理,arr[1] = 22; int[] arr2= {33,44,55};是一个简化的数组形式,实际也是通过new关键字来创建出的数组。所以在都内存中会开辟另一个的空间,并记录了地址值,并赋值给arr2.并且给了初始值,索引为0,1,2. System.out.println(arr2);就是打印arr2在堆内存中的地址值 System.out.println(arr2[0]);首先通过数组名arr2找到存储在堆空间的第二个空间,然后通过索引0,找到对应的值,并打印。其他也是同理。
总结:
- 只要是new出来的一定是在堆内存中开辟了一个空间
- 如果new了多次,那么在堆里有多个小空间,每个小空间中都有各自的数据。