java中关于栈、堆、常量池介绍和关于String类的理解
2015-05-13 19:10
369 查看
栈、 常量池、 堆各自存放什么样的数据类型?
栈:存放基本类型的变量数据和对象的引用。像int a = 1; String str = "hello" ; String str1 = new String("OK") ; 栈中存放的是 a, 1, str, str1。常量池:存放基本类型常量和字符串常量。
堆:存放所有new出来的对象。
对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
而对于字符串来说,其对象的引用都是存储在栈中的,如果是编译期已经创建好(即指用双引号定义的)的就存储在常量池中,如果是运行期(new出来的对象)则存储在堆中。对于equals相等的字符串,在常量池中是只有一份的,在堆中则有多份。
举例看下吧:String str1="abc";
String str2="abc";
String str3="abc";
String str4=new String("abc");
String str5=new String("abc");
对于浅蓝色箭头,通过new操作产生一个字符串(“abc”)时,会先去常量池中查找是否有“abc”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此“abc”对象的拷贝对象,所以,对于String str=new String("abc"),如果常量池中原来没有"abc"则产生两个对象,否则产生一个对象。
这里插入一段题外话:有 int a= 3; int b = 3;编译器首先处理int a = 3;先是在栈中建立一个变量为a的引用,然后在栈中查找是否有字面值为3的地址,若没找到,就在栈中开辟一个空间来存放3这个字面值的地址,然后将a指向3的地址。接下来编译器处理int b = 3;同样在栈中建立b的引用变量后,由于在栈中找到了有3这个字面量的值,便直接将b指向了3的地址,这样a,b都同时指向了3这个字面量地址。如果我们接下来声明 a = 4;那会发生什么呢?这时在编译器内部,它会重新搜索栈中是否存在有4这个字面值,若有,则将a指向这个4字面值的地址,若没有,则在栈中自己开辟一个,然后指向它,不会影响b的指向。
而对于String str1 = "abc"; Sring str2 = "abc"; String str3 = new String("abc"); 编译器的处理是这样的: 先遇到String str1 = "abc"; 首先在栈中建立一个str1的引用,然后在栈中查找是否存放为"abc"的地址("abc"存放在常量池中,引用在栈中),找到就指向它,没有就在常量池中造一个,然后也指向它。接着Sring str2 = "abc";
因为常量池有了"abc",所以str2就也指向它,最后到了String str3 = new String("abc"); 先在栈中建立一个引用str3,然后去常量池中查找是否有“abc”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此“abc”对象的拷贝对象,所以,对于String str=new String("abc"),如果常量池中原来没有"abc"则产生两个对象,否则产生一个对象。
java采用这些机制的目的也就是希望节省内存空间了,经常用到的而且又是不怎么变化的数据,就让大家一起分享!
参考来源:http://blog.sina.com.cn/s/blog_6c663fa50100q5jp.html
相关文章推荐
- java中关于栈、堆、常量池介绍和关于String类的理解
- java中栈.堆.常量池和关于String类的理解
- Java 中关于常量池与缓存类的一点理解
- java String类常量池分析及"equals"和"==”区别详细介绍
- 关于java内存管理和类型的理解
- 关于Java的一些图形awt介绍
- Java中String类的一些理解
- 自我理解关于Java的值传递和引用传递
- java常量池理解与总结
- Java中四种引用强 软 弱 虚 的详细介绍及理解
- Java中的字符串常量池详细介绍
- 详细介绍Java中的堆、栈和常量池
- 关于Spring封装Java线程池的理解
- java中关于数组的介绍
- 关于Java的反射机制,你需要理解这些..
- 关于java synchronized关键字的一些理解
- 关于Java EE的介绍
- 关于JAVA线程的理解
- Java之String常量池的理解
- 关于Java堆栈的简单理解