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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

5黑马币
先看看一个类
  • public class Demo{
  • //这里new出来的是在堆内存中,s1指向堆内存中的地址
  • String s1=new String("abc");
  • //这里"cba"是在栈内存中,s2指向栈内存中的"cba";
  • String s2="cba";//第一个问题:这里"cba"也叫对象是吗?
  • public void Demo(){}
  • }





那么第二个问题来了??????
如果我们在另一个类中
Demo d=new Demo();
那么d.s2是在哪里?堆还是栈中?

哪位大神帮我分析一下???:dizzy:

最佳答案

查看完整内容

不是指向栈。d.s2是变量名,变量名是给人看的,变量在编译后是没有名字了,就是内存地址,这个内存地址是位于JVM的栈空间的,地址中保存的内容指向堆。常量池不是在栈中的,在方法区。每个类都有一块自己的方法区,上面保存这个类自己的常量,有哪些方法之类的信息。

21 个回复

倒序浏览
本帖最后由 342508558 于 2015-6-25 21:50 编辑
挥斥方遒 发表于 2015-6-25 14:55
意思就是d.s2是指向栈了?

不是指向栈。d.s2是变量名,变量名是给人看的,变量在编译后是没有名字了,就是内存地址,这个内存地址是位于JVM的栈空间的,地址中保存的内容指向堆。常量池不是在栈中的,在方法区。每个类都有一块自己的方法区,上面保存这个类自己的常量,有哪些方法之类的信息。

点评

感谢你的耐心回答。。分给你了。。但是网上有各种说法,现在就是有点闹不明白。有的说常量池在栈中,有的说在方法区中。还有的说方法区在堆中  发表于 2015-6-26 12:40
回复 使用道具 举报
本帖最后由 野驴少东 于 2015-6-20 23:33 编辑

我觉的cba不是对象,只不过赋值给s2,它在堆中。属于类的常量
至于第二个问题,Demo和另一个类是什么关系了,d.s2是调用另一个类的常量吧~!
回复 使用道具 举报
d.s2是变量,存在栈中,d.s2指向"cba",“cba”编译时就能确定了,存在常量池。d.s1是变量,存在栈中,d.s1指向new出来的对象在堆中。new String(“abc”)生成了两个对象,一个是存在常量池的"abc",一个是s1指向的对象。
回复 使用道具 举报
本帖最后由 多多洛_sVwLP 于 2015-6-21 00:10 编辑
  1. //这里"cba"是在栈内存中,s2指向栈内存中的"cba";
  2. String s2="cba";//第一个问题:这里"cba"也叫对象是吗?
复制代码


先纠正第1行:"cba"不是在栈内存,他是存在于方法区(也是堆)的常量池中。
答第一个问题:"cba"不能称之为对象,正确说法应该是“字符串常量”,另外对象是通过new这个关键字创建出来的。


如果我们在另一个类中
Demo d=new Demo();
那么d.s2是在哪里?堆还是栈中?

答第二个问题:d因为是变量,所以存在于栈内存中,s2是存在方法区中。

补充:堆是包含方法区的,方法区主要存放:类的代码信息(s2存在这里),static变量,常量池("cba"存在这里)。


希望我的回答能帮到你。望采纳。
回复 使用道具 举报
本帖最后由 JJJD 于 2015-6-21 00:51 编辑

第一个问题:
  1. String s1=new String("abc");
复制代码

语句:创建一个String对象“abc”.
其中:s1存放在栈内存中,“abc”存放在堆内存中。
s1指向了“abc”在堆内存中分配的地址。

  1. String s2="cba";
复制代码

语句:创建一个String对象“bca”.
其中:s2存放在栈内存中,“bca”存放在常量池中。
“cba”也叫对象,不过这个对象是一个字符串常量。

第二个问题:
以下面的java文件为例:
  1. class Demo{
  2.         String s1=new String("abc");
  3.         
  4.         String s2="cba";        
  5. }

  6. public class StringTest1{
  7.         public static void main(String[] args)
  8.         {
  9.                 Demo d=new Demo();
  10.                 String s3=d.s1;
  11.                 String s4=d.s2;
  12.                
  13.                 System.out.println("s3="+s3);
  14.                 System.out.println("s4="+s4);
  15.         }
  16.                
  17. }
复制代码

结果:
s3="abc"
s4="cba"
假设s4创建一个对象,那么s4创建的对象"cba"等于class Demo{}中s1的对象“cba”字符串常量。
但是在常量池中,若常量池中没有就会创建一个,若常量池中已经存在就创建零个。
所以s4的对象“cba”在常量池中已经存在,所以不再创建。所以d.s2存在于常量池中。
回复 使用道具 举报
String是一个特殊的娄,所有的字符串都可以看是一个对象存在,因为它们都可以调方法;需要注意的是:String s1=new String("abc"); String s2="cba";这两个对象最终都是指向方法区常量池的;不同的是s1是关键字new出来,会在堆内存中创建一个对象;而s2是直接指向方法区的;s1---堆----常量池     s2---常量池;第二个问题其实也很简单;所有实例变量都是存在堆中的,只不过String是一个特殊的娄,d.s2其实也是一个对象。
回复 使用道具 举报
堆里,对象都是在堆里的
回复 使用道具 举报
问题1 你把它理解成对象就可以了,你可以把s2看成一个指向方法区常量池中一个char[] 的一个引用。

" " 双引号之中的东西多在方法区常量池中,它是一个char 类型的数组,定义的变量无论是在堆中还是在栈中,最后都会指向方法区中的这个 char数组。

所以问题2 d.s2 是一个存在于堆中的 指向 常量池中 {'c','b','a'} 这个char 数组的一个变量, d.s2存储这 char 数组的 内存地址。
回复 使用道具 举报
你好!很高兴能为你解答:
      第一问答:“cba”是字符串常量,存在方法区中的常量池中;S2指向常量池中的“cba”,"cba"不是对象,是对象中的常量值。
      第二问答:d.s主要是指:对象在堆中存储常量池中“abc”所在对象的地址,并指向字符串对象,从而调用它。
回复 使用道具 举报
这个我也没搞懂
回复 使用道具 举报
首先要区分是变量还是对象;变量在栈里,对象在堆里
回复 使用道具 举报
在堆内存中,d是Demo实例化的一个对象,s2作为对象d的一个个字段,存放在分配给对象d的堆内存中.
回复 使用道具 举报
kime 中级黑马 2015-6-24 18:16:58
14#
首先字段s1,s2是类Demo的成员变量,第一个问题"cba"是字符串常量,第二个问题类的字段都会存在堆中。第6行中的构造函数写的不对应该写成public  Demo(){},构造函数是没有返回值的。
回复 使用道具 举报
cba在常量池中,你newDemo的调用s2的时候,会在堆内存开辟空间,然后用cba这个常量初始化s2;
回复 使用道具 举报
判断此时一个东西是不是对象,最好的方法就是使用getClass()函数,如果不是对象,那肯定不是Object的子对象,那编译时,肯定就会出错了。
回复 使用道具 举报
野驴少东 发表于 2015-6-20 23:26
我觉的cba不是对象,只不过赋值给s2,它在堆中。属于类的常量
至于第二个问题,Demo和另一个类是什么关系了 ...

是的,是的。。。但是 s2指向的常量是 堆里头还是在栈里头呢???
回复 使用道具 举报
342508558 发表于 2015-6-20 23:56
d.s2是变量,存在栈中,d.s2指向"cba",“cba”编译时就能确定了,存在常量池。d.s1是变量,存在栈中,d.s ...

意思就是d.s2是指向栈了?
回复 使用道具 举报
多多洛_sVwLP 发表于 2015-6-21 00:07
先纠正第1行:"cba"不是在栈内存,他是存在于方法区(也是堆)的常量池中。
答第一个问题:"cba"不能称之 ...

java虚拟机中 内存 总共分三个吧 堆、栈、方法区。。我觉得方法区不应该是在堆中。
回复 使用道具 举报
多多洛_sVwLP 发表于 2015-6-21 00:07
先纠正第1行:"cba"不是在栈内存,他是存在于方法区(也是堆)的常量池中。
答第一个问题:"cba"不能称之 ...

还有就是,常量池不是在栈内存中吗????
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马