黑马程序员技术交流社区

标题: 菜鸟一枚,请求大神给详细解答一下。。 [打印本页]

作者: 琳以沫    时间: 2014-7-14 09:33
标题: 菜鸟一枚,请求大神给详细解答一下。。
String aa="abc";
String bb=new String("abc");
System.out.println(aa==bb);

我想的是aa里面的内容是“abc”而bb里面的内容也是“abc”呀,只不过它们前一个没有存储空间,而后一个有存储空间。可以它们的内容是一样的呀。 为啥比较后出来的结果是false??

作者: blue_sky    时间: 2014-7-14 11:08
看下面两个例子,你就明白了;
1. String str1 = "abc";
    System.out.println(str1 == "abc");

步骤:
1) 栈中开辟一块空间存放引用str1;
2) String池中开辟一块空间,存放String常量"abc";
3) 引用str1指向池中String常量"abc";
4) str1所指代的地址即常量"abc"所在地址,输出为true;



2. String str2 = new String("abc");
    System.out.println(str2 == "abc");

步骤:
1) 栈中开辟一块空间存放引用str2;
2) 堆中开辟一块空间存放一个新建的String对象"abc";
3) 引用str2指向堆中的新建的String对象"abc";
4) str2所指代的对象地址为堆中地址,而常量"abc"地址在池中,输出为false;
作者: IT初学者    时间: 2014-7-14 11:53
初学者,不是很清楚,想问2楼,这个两个字符串之间比较不是不能用==,应该用equals方法吗?字符处用==不是只是检测二者是否指向同一个对象的吗?
作者: 徐非    时间: 2014-7-14 12:51
本帖最后由 徐非 于 2014-7-14 12:57 编辑

2楼讲得很详细。
正好刚看到毕老师的数组部分的视频,讲到内存结构,结合笔记说说我个人的理解,不对的地方请大家多多指点

笔记内容:
内存结构:Java程序在运行时,需要在内存中分配空间。为了提高运算效率,又对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。              栈内存:用于存储局部变量,当数据使用完,所占空间会自动释放。
              堆内存:数组和对象,通过new建立的实例都存放在堆内存中。
                            每一个实体都有内存地址值
                            实体中的变量都有默认初始化值
                            实体不在被使用,会在不确定的时间内被垃圾回收器回收
              方法区,本地方法区,寄存器
  1. String aa="abc";
  2. String bb=new String("abc");
  3. System.out.println(aa==bb);
复制代码

个人理解,变量aa和bb都存放在栈内存中,变量aa的值就是初始化值"abc",而变量bb的值是String类型对象"abc"在堆内存中的地址,"abc"肯定不等于一个地址了





作者: 崔MQ    时间: 2014-7-14 13:03
aa和bb引用的都是"abc"这个常量,但是aa和bb是不同的内存地址,而==是数值比较,如果你用aa.equal(bb)那么输出的是true
作者: gdbd419    时间: 2014-7-14 14:10
String是引用类型,
引用类型存在的是地址的指针
你如果直接用==比较的是地址值,即使你存放在堆内存中的内容是一样的但是他们 的指针是指向的两个位置
我觉得是这样


作者: 琳以沫    时间: 2014-7-14 16:11
崔MQ 发表于 2014-7-14 13:03
aa和bb引用的都是"abc"这个常量,但是aa和bb是不同的内存地址,而==是数值比较,如果你用aa.equal(bb)那么 ...

你前面说aa,bb的值是一样的,后面说“==”是数值比较,那这样因该“==”输出的结果为True;而比较内存地址的equal(),应该为False吧,aa,bb它们放置的内存地址是不一样的呀。。
作者: 琳以沫    时间: 2014-7-14 16:14
blue_sky 发表于 2014-7-14 11:08
看下面两个例子,你就明白了;
1. String str1 = "abc";
    System.out.println(str1 == "abc");

也就是说这俩种存放方式是栈,,和堆的问题。。是不是这样理解???
作者: 肖晨    时间: 2014-7-14 16:25
:L一个是变量,一个是地址,怎么能是一回事呢?
作者: 崔MQ    时间: 2014-7-15 12:00
琳以沫 发表于 2014-7-14 16:11
你前面说aa,bb的值是一样的,后面说“==”是数值比较,那这样因该“==”输出的结果为True;而比较内存地 ...

aa,bb在内存中有各自的地址,而==是数值比较,所以它比较的是aa,bb的地址去了,而equal函数其实要重写的,在String中已重写,比较的是内容是否相同。
作者: 小七    时间: 2014-7-15 12:57
本帖最后由 小七 于 2014-7-15 13:01 编辑

因为==比较的是对象也可以称为内存地址,String aa = "abc"只有一个对象,而String bb = newString("abc");有两个对象,一个是"abc"的对象,一个是new String的对象。对象的数量都不一样。比较肯定为false。
作者: 郑飞    时间: 2014-7-15 13:52
我记得好像论坛哪里有==和equals的专贴 我找找 找到了再来发链接
作者: 琳以沫    时间: 2014-7-18 10:27
blue_sky 发表于 2014-7-14 11:08
看下面两个例子,你就明白了;
1. String str1 = "abc";
    System.out.println(str1 == "abc");

好的。。谢谢了。。
作者: 琳以沫    时间: 2014-7-18 10:29
徐非 发表于 2014-7-14 12:51
2楼讲得很详细。
正好刚看到毕老师的数组部分的视频,讲到内存结构,结合笔记说说我个人的理解,不对的地方 ...

谢谢了。。。:)
作者: 郭良    时间: 2014-7-18 10:29
引用,赋值,肯定不一样
作者: F@C    时间: 2014-7-18 11:31
进来学习
作者: 琳以沫    时间: 2014-7-18 11:42
肖晨 发表于 2014-7-14 16:25
一个是变量,一个是地址,怎么能是一回事呢?

这个,,我也是,,通过前面大神的,,讲解和自己测试了,,才明白。。
作者: star5603    时间: 2014-7-18 12:16
aa是变量吧,bb是个对象。用“==”结果是false。
要用String的equals方法比较内容才会是true。“==”比的是地址值。

作者: shen7518    时间: 2014-7-18 13:12
2楼很详尽。。。同意
作者: 導ぷ仙″兲蕐    时间: 2014-7-18 13:38
一个在栈空间中的,一个在堆空间中的.不是一个对象
作者: 柳超    时间: 2014-7-18 14:06
这个是视频第十三天的内容
作者: 柳超    时间: 2014-7-18 14:10
字符串定义出来后保存在堆内存中,而名字就是aa保存在栈内存中,aa中保存的的是字符串的索引也就是字符串在堆内存中的地址值,而你上面的两个定义方式是导致他们==是false的主要原因,字符串本身就是一个对像,你第一种定义方式只有一个对像就是“abc”而你的第二个定义方式有两个对象new一个“abc”又是一个,详细内容你可以看看第十三天的第一个视频
作者: 帮帮    时间: 2014-7-18 14:38
本帖最后由 帮帮 于 2014-7-18 14:46 编辑

我是借助概念和图来理解的:

栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)

堆:存放所有new出来的对象。

常量池:存放字符串常量和基本类型常量(public static final)。

附上图片解析:



作者: 李云贵    时间: 2014-7-18 16:55
这个是对象的创建。简单来说,new 是不管内存中是否已经有相同内容的字符串,直接创建新对象。而==是测试两个类的引用是否指向同一个对象,很明显aa和bb不是同一个对象的,所以返回FALSE。楼主说的内容一样,那是equal,equal才是比较字符串内容的。表达能力不好,不知道有没有说明白




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2