黑马程序员技术交流社区

标题: String类的问题 [打印本页]

作者: 朱晓盼    时间: 2014-4-17 10:13
标题: String类的问题
String s2 = new String("abc");
——————————————————————————
s2在内存中有两个对象,是说s2指向两个对象吗?那么这两个对象的内存地址值相同还是不同?在内存中是什么状态,最好画个图说明下,麻烦各位了,谢谢
作者: ⒈心只霸占沵    时间: 2014-4-17 10:21
http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html
很详细,希望对你有帮助
作者: 朱晓盼    时间: 2014-4-17 10:38
⒈心只霸占沵 发表于 2014-4-17 10:21
http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html
很详细,希望对你有帮助

谢谢,看过了,不过还有疑问,s2在内存中有两个对象,那么就是说s2指向两个对象,s2不可能存储两个地址值吧,或者是他们的内存地址值相同?那不就是一个对象了吗?
作者: ⒈心只霸占沵    时间: 2014-4-17 10:49
s2指向的是一个对象啊    指向的是“abc”这个对象
作者: 呆呆沙师妹    时间: 2014-4-17 10:55
String类比较特殊,它有个字符串常量池,那篇博客中提到过。字符串常量池中相同字符串只能有一份,但new构造器的则不同,每次调用构造器,都在堆内存中创建一个字符串对象,无论字符串常量池是否存在该字符串。在堆内存中,相同的字符串可以存在多个。
这个题String s2 = new String("abc");
它会在堆内存中创建“abc”字符串,同时检查字符串常量池是否存在这个这符串,如果没有,将在字符串常量池创建这个字符串对象,两者的地址是不一样的。s2得到的是堆内存中字符串的地址。
String s = “abc”;这种方式创建时,创建的字符串常量存在于字符串常量池中,返回的是字符串常量池中字符串的地址。
作者: 月光海    时间: 2014-4-17 10:57
s2在创建之后,需要在堆内存中创建一个对象,也就是new一个对象,由于调用了String类的构造函数,往里传了一个“abc”,abc也是一个对象,传之前,先去字符串池寻找abc,找到了,就将对象的引用返回,没找到就创建对象将引用返回,因此,一个对象在堆中,一个对象在字符串池中
作者: 呆呆沙师妹    时间: 2014-4-17 10:59
本帖最后由 呆呆沙师妹 于 2014-4-17 11:05 编辑

你可以用下面这些代码试验一下,用intern() 方法可取出与堆内存中字符串相同的存在于字符串常量池中字符串的地址。它们地址是否相等用“==”判断即可
  1. String s = new String("abc");
  2. String s1 = "abc";
  3. String s2 = new String("abcabc");
  4. System.out.println( s1 == s );
  5. System.out.println( s1 == s.intern() );
  6. System.out.println( s2 == s2.intern() );
复制代码

作者: 清风有意    时间: 2014-4-17 11:29
new String(String str)的源代码如下:
  1.     public String(String original) {
  2.         this.value = original.value;
  3.         this.hash = original.hash;
  4.     }
  5.   public int hashCode() {
  6.         int h = hash;
  7.         if (h == 0 && value.length > 0) {
  8.             char val[] = value;

  9.             for (int i = 0; i < value.length; i++) {
  10.                 h = 31 * h + val[i];
  11.             }
  12.             hash = h;
  13.         }
  14.         return h;
  15.     }
复制代码

首先==这个符号是什么意思要明白。当比较的是对象时,而不是进本数据类型时,==号比较的是地址值,而地址值不一定是hashCode值,因为hashCode被复写了就不是了,在Object类中地址值等于hashCode值。
在new对象时,需要在堆内存中分配空间,地址值是唯一的。这个要和“哈希表数据结构”分清楚。

作者: Holy丶谢特     时间: 2014-4-17 11:56
应该是S2为一个对象,new string()为一个对象,且字符串abc存储于new string()对象中,然后将new string()在内存中的地址赋值给s2.
作者: 朱晓盼    时间: 2014-4-17 12:08
⒈心只霸占沵 发表于 2014-4-17 10:49
s2指向的是一个对象啊    指向的是“abc”这个对象

那么new这个对象呢?s2不指向吗?那岂不是会被当做 垃圾回收了?
作者: ⒈心只霸占沵    时间: 2014-4-17 12:21
朱晓盼 发表于 2014-4-17 12:08
那么new这个对象呢?s2不指向吗?那岂不是会被当做 垃圾回收了?

int a = 1;1会存放在栈里 String s1 = "thanks";thanks会存放在data segment里 String s2 = new String("thanks");thanks会存放在data segment里 String a ="th";String b = "anks";String c =a+b;c会存放在data segment里 字符串全部存放在data segment里 常量池全部在栈里。如果你不new的话,比如你写String s = "thanks";这时s分配在栈里,s直接指向字符池里的"thanks";但如果你这样写,String s; s = new String("thanks");这时s指向堆里的一块内存,这个内存里的地址指向字符池里的"thanks";

对内存是有会有机制的   栈内存没有自动回收机制
作者: 朱晓盼    时间: 2014-4-17 12:35
呆呆沙师妹 发表于 2014-4-17 10:55
String类比较特殊,它有个字符串常量池,那篇博客中提到过。字符串常量池中相同字符串只能有一份,但new构 ...

你说的常量池中的字符串和堆内存中的字符串地址值不同,这个我懂,
但是我问的关键点不在这里
我想搞清楚,new出来的对象和“abc”这个对象在内存中是怎么存在的?
希望能给画张图,我觉得图画出来了,思想就出来了,可是我看了你的理论,根本就画不出图啊:L
作者: 朱晓盼    时间: 2014-4-17 12:47
月光海 发表于 2014-4-17 10:57
s2在创建之后,需要在堆内存中创建一个对象,也就是new一个对象,由于调用了String类的构造函数,往里传了 ...

可以这样理解的吗?


作者: 朱晓盼    时间: 2014-4-17 13:08
⒈心只霸占沵 发表于 2014-4-17 12:21
int a = 1;1会存放在栈里 String s1 = "thanks";thanks会存放在data segment里 String s2 = new String(" ...

常量池在栈里???
我似乎有思路了,哥们能给画张图吗?
作者: 呆呆沙师妹    时间: 2014-4-17 13:22
大概是这样吧,画的有点糟糕。

字符串对象的不同创建方式.jpg (53.56 KB, 下载次数: 12)

字符串对象的不同创建方式.jpg

作者: 朱晓盼    时间: 2014-4-17 13:56
呆呆沙师妹 发表于 2014-4-17 13:22
大概是这样吧,画的有点糟糕。

不是有两个对象吗?你的图中显示只有abc这个对象啊
作者: 呆呆沙师妹    时间: 2014-4-17 14:01
本帖最后由 呆呆沙师妹 于 2014-4-17 14:03 编辑
朱晓盼 发表于 2014-4-17 13:56
不是有两个对象吗?你的图中显示只有abc这个对象啊


"abc"有两个对象,一个在堆内存中,另一个在字符串池中呀
"cde"只有一个,字符串池中的那个
引用变量s1存储的地址是堆内存中"abc"的地址,用s1.intern()能取到字符串池"abc"的地址;
引用变量s2存储的地址是字符串池"cde"的地址。
作者: 朱晓盼    时间: 2014-4-17 15:20
呆呆沙师妹 发表于 2014-4-17 14:01
"abc"有两个对象,一个在堆内存中,另一个在字符串池中呀
"cde"只有一个,字符串池中的那个
引用变量s1存 ...

原来如此,搞明白了,谢谢你了,真是麻烦你了
谢谢楼上所有帮助我的朋友,谢谢
作者: 左拉    时间: 2014-4-17 15:31
其实这句话分两步理解:
String str1="abc";
String str2=new String("");
str2=str1;
所以new String("abc")表示这个字符串指向abc,但是多new了一个空间出来,所以浪费了内存地址
作者: 心?=忐§忑]    时间: 2014-4-17 16:09
  
    



  

无标题.png (26.74 KB, 下载次数: 14)

无标题.png





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