Java中堆内存(heap)和栈内存(stack)的区别
2015-12-06 12:10
302 查看
在Java代码中,常常会使用到这样的类的声明实例化:
Personper=newPerson();
//这其实是包含了两个步骤,声明和实例化
Personper=null;//声明一个名为Person类的对象per
per=newPerson();//实例化这个per对象
声明指的是创建类的对象的过程;
实例化指的是用关键词new来开辟内存空间。
它们在内存中的划分是这样的:
那什么是栈内存(heap)和栈内存(heap)呢?
Stringstr1="myString";
Stringstr2="myString";
System.out.println(str1==str2);
//注意:这里使用的是str1==str2,而不是str1.equals(str2)的方式。
//因为根据JDK的说明,==号只有在两个引用都指向了同一个对象时才返回真值
//而str1.equals(str2),只是比较两个字符串是否相等
结果为True,这就说明了str1和str2其实指向的是同一个值。
上述代码的原理是,首先在栈中创建一个变量为str1的引用,然后查找栈中是否有myString这个值,如果没找到,就将myString存放进来,然后将str1指向myString。接着处理Stringstr2="myString";;在创建完str2的引用变量后,因为在栈中已经有myString这个值,便将str2直接指向myString。这样,就出现了str1与str2同时指向myString。
特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完str1与str2的值后,再令str1=yourString;那么,str2不会等于yourString,还是等于myString。在编译器内部,遇到str1=yourString;时,它就会重新搜索栈中是否有yourString的字面值,如果没有,重新开辟地址存放yourString的值;如果已经有了,则直接将str1指向这个地址。因此str1值的改变不会影响到str2的值。
Stringstr1=newString("myString");
Stringstr2="myString";
System.out.println(str1==str2);//False
Stringstr1=newString("myString");
Stringstr2=newString("myString");
System.out.println(a==b);//False
创建了两个引用,创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
Personper=newPerson();
//这其实是包含了两个步骤,声明和实例化
Personper=null;//声明一个名为Person类的对象per
per=newPerson();//实例化这个per对象
声明指的是创建类的对象的过程;
实例化指的是用关键词new来开辟内存空间。
它们在内存中的划分是这样的:
那什么是栈内存(heap)和栈内存(heap)呢?
栈内存:
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。栈内存主要存放的是基本类型类型的数据如(int,short,long,byte,float,double,boolean,char)和对象句柄。注意:并没有String基本类型、在栈内存的数据的大小及生存周期是必须确定的、其优点是寄存速度快、栈数据可以共享、缺点是数据固定、不够灵活。栈的共享:
结果为True,这就说明了str1和str2其实指向的是同一个值。
上述代码的原理是,首先在栈中创建一个变量为str1的引用,然后查找栈中是否有myString这个值,如果没找到,就将myString存放进来,然后将str1指向myString。接着处理Stringstr2="myString";;在创建完str2的引用变量后,因为在栈中已经有myString这个值,便将str2直接指向myString。这样,就出现了str1与str2同时指向myString。
特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完str1与str2的值后,再令str1=yourString;那么,str2不会等于yourString,还是等于myString。在编译器内部,遇到str1=yourString;时,它就会重新搜索栈中是否有yourString的字面值,如果没有,重新开辟地址存放yourString的值;如果已经有了,则直接将str1指向这个地址。因此str1值的改变不会影响到str2的值。
堆内存:
堆内存用来存放所有new创建的对象和数组的数据创建了两个引用,创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
相关文章推荐
- JAVA编写的金蝶K3ERP用户审批流层复制工具
- JAVA中其它包中无法引用缺省包(default package)的类 - 使用反射可以
- java程序开发工具集的使用
- Java编程高手对CLASSPATH应用的详细介绍
- Spring.NET学习笔记3——实现一个简易的IoC框架(练习篇) Level 100
- Java中getResourceAsStream的用法
- Spring.NET学习笔记2——环境搭建(基础篇) Level 200
- Java Swing中图标,背景等最好用的类和方法
- Spring.NET学习笔记1——控制反转(基础篇) Level 200
- SpringMVC 中getJSON的使用案例
- Java JDBC封装模式
- Java JDBC封装模式
- 圣思园java se培训总结(22-24)(static , final 陷阱)
- Java Word插入图片
- Struts2+AJax判断用户名是否存在
- Java可变参数应用实操
- JAVA编程思想导论(猜字谜游戏1.0)
- java内部类实例化
- JavaWeb学习(5.5)---在Servlet使用getServletContext()获取ServletContext对象出现java.lang.NullPointerException(空指针)异常的解决办法
- java小说上传txt功能,(同名小说不能再次上传)