黑马程序员技术交流社区

标题: 有关equals和==的问题 [打印本页]

作者: 高欢欢    时间: 2012-7-14 19:33
标题: 有关equals和==的问题
本帖最后由 高欢欢 于 2012-7-18 07:32 编辑

基本数据类型比较只能用==运算符比较是否相等,而引用数据类型==比较的是两个对象的内存地址是否相等,通过覆盖equals的方式,equals可以比较啊两个对象的内容是否相等。
我想问一下,假设有两个对象s1和s2,如果s1==s2结果是true,那么s1.equals(s2)一定为true,这句话对吗?为什么?
作者: 黑马-王言龙    时间: 2012-7-14 19:38
本帖最后由 黑马-王言龙 于 2012-7-14 19:39 编辑

是正确的

两个对象引用==为true,说明指向了同一个内存中的对象,那equals比较也一定为true
作者: 张_涛    时间: 2012-7-14 19:41
  1. public boolean equals(Object anObject) {
  2. //观察下面三行代码,首先判断两个引用是否指向同一对象
  3.         if (this == anObject) {
  4.             return true;
  5.         }
  6. //其次才是比较两个引用所指向的对象的内容是否相等
  7.         if (anObject instanceof String) {
  8.             String anotherString = (String)anObject;
  9.             int n = count;
  10.             if (n == anotherString.count) {
  11.                 char v1[] = value;
  12.                 char v2[] = anotherString.value;
  13.                 int i = offset;
  14.                 int j = anotherString.offset;
  15.                 while (n-- != 0) {
  16.                     if (v1[i++] != v2[j++])
  17.                         return false;
  18.                 }
  19.                 return true;
  20.             }
  21.         }
  22.         return false;
  23.     }
复制代码
以上为String类的equals方法底层实现;
通过观察可以发现无论是系统自己底层实现的equals方法还是自己重写的,一般都是先判断两个引用是否指向同一个对象,如果是,则返回真。
试想,两个引用指向的是同一对象,还有什么是不相等的呢?
因此,如果s1==s2结果是true,那么s1.equals(s2)一定为true,这句话是正确的。


作者: 黑马刘涛    时间: 2012-7-14 19:43
本帖最后由 黑马刘涛 于 2012-7-14 19:57 编辑

问题:假设有两个对象s1和s2,如果s1==s2结果是true,那么s1.equals(s2)一定为true?
每个类都是使用Object作为超类的,所有对象(包括数组)也实现这个类方法。
对于Object类的equals方法如下:
public boolean equals(Object obj) {   
    return (this == obj);   
}  
即是说关于一个普通类,没有作出覆盖equals方法时,改类的比较"=="与equals操作的结果是相同的。
然而当你复写了equals方法,而对象都是new出来的(String类比较特殊除外,比如String str = "abc";如果堆中有一个"abc"常量,就不会new,str直接引用abc的地址),你new了两个对象,就在堆上创建了两个地址不同的对象,理论上s1==s2结果为false,不可能为true。所以你这个问题的前提条件有点问题。
你对自定义类复写了自己应用需要(比如字符串equals方法比较的就是两个串的内容是否相同)的equals方法后,比较就可能不是地址是否相同,而是对象的内容。
作者: 苑占丽    时间: 2012-7-14 20:00
基本数据类型比较只能用==运算符比较是否相等,而引用数据类型==比较的是两个对象的内存地址是否相等,通过覆盖equals的方式,equals可以比较啊两个对象的内容是否相等。
我想问一下,假设有两个对象s1和s2,首先这句话,我觉得楼主问的就有问题呀,如果是两个对象,那就两块内存,而==比较的就是内存是否相同,所以又何来s1==s2结果是true之说呢?如果是两个对象,这个结果一定false。而equals比较的是两个对象的内容是否相同,
如果S s1=new s1();
S s2=new s2();
那这时s1==s2 为false,s1.equals(s2)为true

而当S s1=new s1();
S s2=s1
此时s1==s2 定为true,s1.equals(s2)也为为true

这种情况就相当于s1这个对象有两个名字,同时指向的是一个人,你说他们的内存地址能不相同吗,当然内容也相同了,所以引用数据类型只要s1==s2结果是true,那么s1.equals(s2)一定为true,这句话肯定对呀
如果s1==s2结果是true,那么s1.equals(s2)一定为true,这句话对吗?为什么?
作者: 苑占丽    时间: 2012-7-14 20:04
基本数据类型比较只能用==运算符比较是否相等,而引用数据类型==比较的是两个对象的内存地址是否相等,通过覆盖equals的方式,equals可以比较啊两个对象的内容是否相等。
我想问一下,[color=Red]假设有两个对象s1和s2,首先这句话,我觉得楼主问的就有问题呀,如果是两个对象,那就两块内存,而==比较的就是内存是否相同,所以又何
作者: 位雪    时间: 2012-7-14 20:04

感觉你的问题前提条件有点问题,通过两个例子分析一下
例一
public class EqualsMethod {
public static void main(String[] args) {
String str =“wxy//在栈内存中定义一个str1变量,然后在常量池中创建"wxy,然后将地址传给str1str1指向了"wxy"
String str2=new Stringwxy);//在栈内存中定义一个str2变量,然后在堆内存中创建String对象,然后再创建一个wxy,并将其地址传给str2
System.out.println(str1==str2)//这里比较的是地址,一个是常量池的,一个是堆内存的,肯定不一样啊,所以返回false
System.out.println(str1.equals(str2));//这里比较的是内容,所以返回的是true
}
}
例二
class Value
{
int n;
}
public class EqualsMethod1 {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(n1.equals(n2));//这里的equals()用的是Object类中的,没有经过复写,在这里和”==“功能相同,比较的是地址,因为这里是new了两个对象,地址
} //肯定不同,所以返回的是false
}



作者: 咸明月    时间: 2012-7-15 09:25
因为==为true说明他们的是一个内存,他们都是同一个内存了,一个位置只能有一个值,所以他们的值是一个所以为true
作者: 党巾水    时间: 2012-7-16 13:21
如果s1==s2结果是true,那么s1.equals(s2)一定为true,这句话正确。
但是反过来说就是错的。
即:如果s1.equals(s2)为true,则s1==s2一定为true。这句是错误的。
作者: 王海亮    时间: 2012-7-16 13:52
"=="比较的是内存地址,"equals"比较的是值。
当S1==S2为true时内存地址相同,S1和S2引用相同的内存空间,
所以S1的值发生改变时S2的值也随之发生改变。
所以s1.equals(s2)一定为true




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