A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

同样常量池呢,是在栈中吗?

6 个回复

倒序浏览
本帖最后由 黑马_位志国 于 2013-3-6 14:29 编辑

1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。Java是自动管理栈和堆,程序员不能直接地设置栈或堆。   

2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器,栈数据可以共享 。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
    堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

使用【String str = "abc";】的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。
而对于【String str = new String("abc");】的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
Java虚拟机内存里面专门为string类型变量开辟的一片区域,那就是字符串池,保存着几乎所有的字符串对象。字符串表达式总是指向字符串池 中的一个对象。使用new操作创建的字符串对象不指向字符串池中的对象但是可以使用intern方法使其指向字符串池中的对象(注:如果池中已经有相同的 字符串--使用equals方法确定,则直接返回池中的字符串,否则先将字符串添加到池中,再返回)。池中两个相等的字符串如果使用“==”来比较将返回 真。
常量池
虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。而JVM中的常量池在内存当中是以表的形式存在的,对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。
回复 使用道具 举报
以下是我以前收藏的技术文档,很详细,看一遍后,思路立马就清晰啦
说到java中堆、栈和常量池,首先还是看看他们各自存放的数据类型吧!

堆:存放所有new出来的对象;栈:存放基本类型的变量数据和对象的应用,对象(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"则产生两个对象,否则产生一个对象。
   而对于基础类型的变量和常量,变量和引用存储在栈中,常量存储在常量池中。例如:
此处看第二个图片
此处看第三个图片

对于成员变量和局部变量来说,成员变量是方法外部,类得内部定义的变量。局部变量就是方法或语句块内部定义的变量,注意,局部变量必须初始化。
     局部变量(形式参数)的数据存于栈内存中,并且它(局部变量)随方法的消失而消失。

show_mop.jpg (29.64 KB, 下载次数: 118)

1

1

show_mp.jpg (13.15 KB, 下载次数: 120)

2

2

show_mo.jpg (14.32 KB, 下载次数: 118)

3

3

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

回复 使用道具 举报
wz999hmlt 发表于 2013-3-6 14:38
程序中用来存放数据的内存分为四块,另有一块用于存放代码

1、方法区:存放全局变量和静态变量都存储在这 ...

谢谢,明白点了,一直以为内存只分为堆栈,常量池在栈中,原来是独立出来的。
回复 使用道具 举报
克零岚 发表于 2013-3-6 14:41
以下是我以前收藏的技术文档,很详细,看一遍后,思路立马就清晰啦
说到java中堆、栈和常量池,首先还是看 ...

谢谢,很详细,不过我记着是通过String str = new String("abc");方式创建字符串时如果常量池中没有“abc”这个字符串也不往里面添加啊?难道没有的话,现在常量池里加一个,然后再复制到堆内存中?
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马