黑马程序员技术交流社区

标题: String类 为什么要重写 object 中 equals 方法 [打印本页]

作者: 郭帅帅    时间: 2014-4-5 18:51
标题: String类 为什么要重写 object 中 equals 方法
本帖最后由 郭帅帅 于 2014-4-6 20:32 编辑

我自己推测的,不知道不对不。
就是String字符串在内存中同样内容的字符串只能存在一个,要是再new出一个同样内容的串,那么这个引用同样会指向这个字符串对象。类似于这样:
  1. String str1 = new String("abc");
  2. String str2 = str1;
复制代码

注意!这个时候,再用父类object中equals方法比较这两个字符串的地址是毫无意义的,就是说结果肯定是true,那么那些java工程师就考虑说定义String中equals方法覆盖一下上帝类的equals方法吧,然后就在覆盖之后定义自己特有内容:比较字符串内容是否相等。
望大神指正批评!
作者: xuehuayous    时间: 2014-4-5 19:16
个人感觉没有那么复杂吧,String中equals方法就是方便比较两个字符串的内容是否相等。
作者: linweiwen    时间: 2014-4-5 19:30
本帖最后由 linweiwen 于 2014-4-5 21:21 编辑

楼主我觉得你前半部分某程度上是对的,后半部分就不太合适。

首先,你的代码,只是将"对象引用"str1又赋值给str2,这样str2就会指向str1这个"对象引用"的实际对象。
这个过程,仅仅是涉及到了堆内存和栈内存中"对象引用"怎样指向的问题。

那么如果是下面这样呢?
  1. String str1 = new String("abc");
  2. String str3 = new String("abc");
复制代码
根据Java把字符串常量放字符串常量池的做法,
"abc"这个字符串是放在字符串常量池中,
str1和str3这两个"对象引用"它们的地址值会不一样,
而它们指向的String对象也不一样,但内容相同。

至于说“String类 为什么要重写 object 中 equals 方法”,
貌似没有这种说法,只有"重写equals方法要同时重写hashcode()方法"的说法。
你日常比较String类的对象,就记住equals()方法只比较内容,== 方法还会比较地址 就OK了。

  1. /*
  2. * 目的:探讨String类中的equals方法
  3. * */
  4. public class StringTest {
  5.         public static void main(String[] args) {
  6.                 String str1 = new String("abc");
  7.                 String str2 = str1;
  8.                 String str3 = new String("abc");
  9.                 String str4 = "abc";
  10.                 System.out.println(str1.equals(str2)); // true
  11.                 System.out.println(str1.equals(str3));// true
  12.                 System.out.println(str1.equals(str4));// true
  13.                 System.out.println(str1.hashCode());// 96354
  14.                 System.out.println(str2.hashCode());// 96354
  15.                 System.out.println(str3.hashCode());// 96354
  16.                 System.out.println(str4.hashCode());// 96354
  17.                 System.out.println(str1 == str2); // true
  18.                 System.out.println(str1 == str3);//false
  19.                 System.out.println(str1 == str4);// false
  20.         }
  21. }
复制代码

看上面程序的输出,就一目了然。






作者: 宋丹    时间: 2014-4-5 19:31
Object类中的equals比较的是hascode的地址,所以新建类如果不复写的话,比较肯定是true;一般新建类都要复写equals方法
作者: 郭帅帅    时间: 2014-4-5 20:21
linweiwen 发表于 2014-4-5 19:30
楼主我觉得你前半部分某程度上是对的,后半部分就不太合适。

首先,你的代码,只是将"对象引用"str1又赋值 ...

恩,是不太合适,有点片面!
不过,你举的例子有错误唉
str1==str3   结果是false
str1==str4  结果也是false
因为str1里面有两个对象,str3也有两个对象,str4里面之后一个对象,
str1和str4相比自然是false,至于str1和str3为什么不相等我也搞不明白
作者: 郭帅帅    时间: 2014-4-5 20:34
郭帅帅 发表于 2014-4-5 20:21
恩,是不太合适,有点片面!
不过,你举的例子有错误唉
str1==str3   结果是false

就是因为str1和str3在new 对象的时候,所引用的地址值不一样,所以str1==str3结果为false吗?关于这个常量池,不太懂,还望多指教!
作者: linweiwen    时间: 2014-4-5 20:35
本帖最后由 linweiwen 于 2014-4-5 20:37 编辑
郭帅帅 发表于 2014-4-5 20:21
恩,是不太合适,有点片面!
不过,你举的例子有错误唉
str1==str3   结果是false

噢,不好意思,我那些注释是复制粘贴的,
上面那个哈希值复制习惯了,
下面也没管,弄完这个程序我又开始写回复,没有留意。
实在很抱歉,马上改过来。
作者: linweiwen    时间: 2014-4-5 20:56
本帖最后由 linweiwen 于 2014-4-5 20:58 编辑



我那个程序那些内存指向大概就是上图这样,
另外字符串常量池不是我画的那个样子,
实际上要复杂得多,画那样方面你理解,
就当是一个有索引对应字符串的表格就好了。

字符串常量池在常量池中,常量池在方法区中。
上面两个分别是栈和堆。

你看各个"对象引用",它们实际指向那个对象的所在,
就能明白为什么str1和str3比较是false了

作者: 郭帅帅    时间: 2014-4-5 22:43
linweiwen 发表于 2014-4-5 20:56
我那个程序那些内存指向大概就是上图这样,
另外字符串常量池不是我画的那个样子,
实际上要复杂得多,画 ...

恩,大概明白,还是感谢你的解答啊。深一点理解的话,我得去查阅资料了,常量池,内存空间,还有什么克隆,好复杂




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