黑马程序员技术交流社区

标题: "abc"究竟是个常量还是个对象,放在那里?堆内存还是常量区 [打印本页]

作者: 刘凯    时间: 2013-2-6 16:43
标题: "abc"究竟是个常量还是个对象,放在那里?堆内存还是常量区
本帖最后由 刘凯 于 2013-2-7 18:06 编辑

现在就是这个问题,"abc" 是一个对象还是个常量? 毕老师的视频里又说过"abc"是建立了一个String对象,  但又看到别的帖子说,"abc"是一个常量。

s1="abc";
s2="abc";
s1 == s2;//ture.


1.如果是个"abc"常量,无可厚非,是放在常量区里,s1 s2都指向同一个,s1 == s2;//ture. 那就没错了。


2.如果是对象,那么应该是两个相同的对象,== 应该比较的应该是 hashCode() 这个值是否相同 , 所以s1 和 s2 主要的不同就在hashCode()返回值上, 又查了下String类的hashCode()   

结果 String类的hashCode()  覆盖了Object类中hashCode()方法

返回此字符串的哈希码。String 对象的哈希码根据以下公式计算:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用 int 算法,这里 s 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希值为 0。)
所以说 s1  s2 所指向的两个对象由于都是"abc"  所以其hashCode()返回值是相同的  
  所以 s1==s2 是true

所以s1 == s2;//ture.第二种说法也能讲的通了

现在就是有这个问题  到底"abc"是个常量  还是个对象?   反正毕老师的视频上说是"abc"是建立了一个对象  我感觉也应该是一个对象,不知道楼下有什么见解


作者: 胡发友    时间: 2013-2-6 17:23
我的理解是,
      String = "abc";是个常量,java的API里说的是等效
      char data[] = {'a', 'b', 'c'};
      String str = new String(data);,
就是说产生的效果是一样的,都能生成字符串abc,但是他们不在一个地方,常量在栈中,而new String是在堆中,所以他们用 "=="比的是时候,返回的是false;

而用equals比的时候,返回的是true,因为equals是判断他们是不是属于同一个类型,
作者: 胡发友    时间: 2013-2-6 17:26
补充:纠正   常量是放在常量池中
作者: 刘凯    时间: 2013-2-6 17:37
本帖最后由 刘凯 于 2013-2-7 18:07 编辑
胡发友 发表于 2013-2-6 17:23
我的理解是,
      String = "abc";是个常量,java的API里说的是等效于,
      char data[] = {'a', 'b', ...


按毕老师的说法String str = new String("abc");是定义了两个对象,  那也就是说"abc"是一个对象喽 ,再有
equals方法在String类是复写了的 ,复写为比较String中的字符串是否相同,而并不是Obeject类中的比较hashCode(),
若按您所说equals是判断他们是不是属于同一个类型  
那String s1 =“a”;
String s1 =“b”;
s1 s2都应该是String类型的那么 a.equals(b)也是true   这显然是不对的
而 == 我认为应该是和Object类中的equals()方法是相同的  也就是说
如果你自定义的类中复写了equals方法 还是可以有 == 来判断两个对象的
hashCode()是否相同

所以我还是认为"abc"是一个对象,而不是一个常量

作者: 胡发友    时间: 2013-2-6 18:01
刘凯 发表于 2013-2-6 17:37
按毕老师的说法String str = new String("abc");是定义了两个对象,  那也就是说"abc"是一个对象喽 ,再 ...

你说的是对的
作者: 黄成超    时间: 2013-2-8 11:13
本帖最后由 黄成超 于 2013-2-8 11:16 编辑

JDK开发文档String类中有里有明确说明,所有的字符串的字面值,如“abc”都作为String类的实例实现,String str = "abc";
等效于:
     char data[] = {'a', 'b', 'c'};
     String str = new String(data);
所以,字符串"abc"都是String类的实例对象,所以new String  str = new String("abc"),相当于String str = new String(new String(data)); //data为char data[] = {'a','b','c'}
所以说,”abc“是一个常量,但也相当于一个对象。(这些在jdk开发文档都有说明的,可以查看String类中哦!)
作者: 刘凯    时间: 2013-2-8 14:40
黄成超 发表于 2013-2-8 11:13
JDK开发文档String类中有里有明确说明,所有的字符串的字面值,如“abc”都作为String类的实例实现,String ...

看到你的帖子了啊   已经  
作者: 黄玉昆    时间: 2013-2-8 19:00
对于String是很特殊的一种类型。你在每次String s1 =  "abc";或者String s2 = "abc";的时候,是会在堆内存中产生abc这个对象的。但是String特殊就特殊在:它是被定义为final的,当你String s1 =  "abc";的时候,已经在内存中存在了一个“abc”对象,你再String s2 = "abc";的时候,虽然变量不同了,但是系统会先查看一遍,是不是存在"abc"这个对象,存在了,就让s2也指向"abc",而String s = new String("abc");就不同了,只有有new了,那么就会产生另一个新对象。你可以看看我的测试代码:
  1. class Demo01
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 String s = "abc";
  6.                 String s1 = "abc";
  7.                 String s2 = new String("abc");
  8.                 String s3 = new String("abc");
  9.                 System.out.println("s == s1 :" + (s==s1));
  10.                 System.out.println("s == s2 :" + (s==s2));
  11.                 System.out.println("s3 == s2 :" + (s3==s2));
  12.         }
  13. }
复制代码





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