2020-08-09

JAVA中栈和堆的存储区别

Java中的8大基本类型

表1-1 Java整型
类型存储字节取值范围
byte1字节-128 ~ 127
short2字节-32,768 ~ 32,767
int4字节-2,147,483,648 ~ 2,147,483, 647
long8字节-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
表1-2 Java浮点型
类型存储字节取值范围
float4字节约 ± 3.402,823 47E(有效位数为6 ~ 7)
double8字节约 ± 1.797,693,134,862,315 70E+308(有效位数为15位)
表1-3 Java中char与boolean类型
类型存储字节取值范围
char2字节u\0000 ~ u\ffff (unicode编码)
boolean1字节true/false

Java中栈(stack)和堆(heap)

栈的基本了解

优点:存取速度比堆要快,仅次于寄存器,栈里的数据是可以共享的

缺点:存在栈中的数据大小与生命周期是确定的,缺乏灵活性。

存放的东西:上面的8大数据类型、对象句柄(引用)和方法函数。

堆的基本了解

优点:堆上的对象动态创建,灵活性高。

缺点:速度慢,不能及时释放内存。

存放的东西:new出来的对象。

栈与堆的存储和释放

栈存储与释放

存储:根据上面的知识我们已经知道栈存放的东西有哪些,如在一个方法swap()里面定义一个int a = 2;jvm会在栈上开辟一个未使用的内存给这个方法和变量使用。

释放:随着方法调用完后,他们的内存会立即释放,其他方法可以立即使用这个已释放的内存,这也是在栈上存储速度快的原因。

堆存储与释放

存储:堆上存储的是new出来的对象,当使用xxClass() a = new xxClass()后,对象会在堆上存储,而对象句柄a会存储在栈上,它指向的是堆上对象所在的首地址。

释放:因为对象句柄是存在栈上,而栈上的方法在调用完后会立即释放内存,这样指向堆上的引用就没有了,堆上该对象在没有引用变量指向它后变成垃圾对象,但是堆上存储该对象的内存却还没有释放,也就不能给其他新建对象使用,jvm会在一个不确定的时间里通过垃圾回收器回收这部分内存。这就是为什么Java比较占内存的主要原因。

证实栈上的方法在互不影响的内存里

public class Main {
	
	public static void swap(int a,int b){
	     int t = a;
	     a = b;
	     b = t;
	     System.out.println("进入函数调用:a = "+a+",b = "+b);
	 }
	
	public static void main(String[] args) {
		int a = 2;
		int b = 4;
		swap(a,b);
		System.out.println("调用函数返回:a = "+a+",b = "+b);
	}
}

在这里插入图片描述

图1 栈上方法内存存储

在这里插入图片描述

图2 栈上的存储

       由图2可以看出main()和swap()方法在栈上是在两块互不影响的两块内存中,所以两个方法中定义的变量也是在各自分配的内存上,所以在swap中进行的任何数据操作都对main()中的变量任何影响。

证实栈上存放的对象句柄是指向堆上存放对象的地址

class Dog{
	
	public int age;
	
	public void setAge(int age) {
		this.age=age;
	}
	public int getAge() {
		return this.age;
	}

}
public class Main {
	
	public static void change(Dog dog){
	     dog.setAge(5);
	     System.out.println("进入函数调用:age = "+dog.getAge());
	 }
	
	public static void main(String[] args) {
		Dog dog =new Dog();
		dog.setAge(2);
		change(dog);
		System.out.println("调用函数返回:age = "+dog.getAge());
	}
}

在这里插入图片描述

图3 堆上对象内存存储

在这里插入图片描述

图4 对象的栈和堆的使用

       由图3和图4可知,当创建一个对象的时候,栈上存储的是对象的引用,真正的对象数据是在堆上建立的,栈上的对象引用就指向堆上建立的对象的地址,当main()函数调用change()函数的时候是传了对象的引用过去(也就是堆上对象的地址),然后在change()方法中根据传过来的地址去修改堆上的对象数据,所以即使当栈上change()方法被释放后,堆上的对象数据是已经改变后的。

提出一个问题,String不在Java的8大基本类型中,而且String的定义有两种方式,那么它是存在栈上还是在堆上呢?

       提示一下:在栈上有个String常量池的,也就是说相同的字符串在常量池中只存放一份。可以使用(str1 == str2)来看地址的是否相同。
 
 
 
如果只是向往,远依旧是远方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值