日期:2014-05-20  浏览次数:20706 次

为什么要改写java中Object类的equals方法
我的书上写的是Object中的equals方法是用于检测一个对象是否等于另外一个对象,检测的方法是判断两个对象是否具有相同的引用,如果他们具有相同的引用,他们一定是相等的。但是对于多数类来说这个判断没有什么意义,我想知道为什么这个判断对于多数类来说没有意义。书上并没有给出解释,我想请问一个高手,最好详细一些。

------解决方案--------------------
两个对象,比如两支笔,Object的equals方法是比较这两只笔是不是同一支笔.
这显然是没有任何意义的...
但是你覆盖了equals方法后,就可以让这个方法比较这两支笔是不是一个牌子,是不是一样长,是不是同一种材料..等等
------解决方案--------------------
举个简单的例子:
一个用户登录一个网站,输入用户名和密码,然后提交,在服务器生成一个对象user1,
服务器从数据库提取用户信息,也生成一个对象user2,user1和user2中用户名和密码相同。如果不修改equals()方法,两个对象必然不同(具有相同的引用,他们才是相等的),所有要修改equals()方法:

public boolean equals(Object ob){
User u=(User)ob;
if(u.userName.equals(this.userName)&&u.password.equals(this.password))return true;
else return false;
}

修改阿去啊老师equals()方法与实际的应用有关系。
------解决方案--------------------
String s1 = "asdf ";
String s2 = "asdf ";
s1 == s2 返回false, 但s1.equals(s2) 是返回true.
====================================
这个例子举得有点问题吧,呵呵。
先回答问题:
Object在的equals方法当a.equals(b);时,如果a,b指向的是同一个对象就返回true否则返回false,也就是说它比较的是内存地址,看两个引用引的是不是同一个内存地址:
Student s1=new Student();
Student s2=s1;
s1.equals(s2);//返回true
但是我们的业务中常常比较两个引用是否相等时,不是要看它们地址是否相同,如果要比较地址可以用s1==s2来比较,那么我们通常是要知道两个不同地址的对象,它们的内容是否相同,但什么叫内容相同呢?这就需要根据不同业务来定义了,Object类没办法知道什么叫相同,比如我们可能认为两个学生学号相同就是同一个学生了,那么就可以在equals()方法中比较一下学号就行了,再说一个更极端的例子,比如我完全可以定义任何的条件做为相等条件,只要业务需要,我可以定义85==90为true,因为我认为只要精确到十位相等就认为相等了。

另外说说一般的规则:我们在写equals方法时,要注意满足三个原则:
1、自等性:Student s=new Student();s.equals(s);一定要返回true;
2、反身性:s1.equals(s2)为true时要保证s2.equals(s1)也为true;
3、传递性:s1.equals(s2)为true,并且s1.equals(s3)为true,则s1.equals(s3)要为true;
找一个集成开发环境自动生成一个equals方法,研究一下生成的代码就会发现其中的一些细节。

再说说String类,先说说串池,字符串是程序中使用率非常高的类,为了提高效率,串是用“池”来管理的。
String s1= "asdf ";这个对象不是在堆中,而是在串池中,当再创建一个变量Sting s2= "asdf ";时,会先去池中找,如果有这个字符串存在,就不再新建,而是把s2也指向那个字符串,这样s1和s2就是指向同一个对象了,所以s1==s2是true;但String s3=new String( "asdf ");就不一样了,这是强制在堆空间创建一个对象,这时不指向串池,所以s1==s3是false;但s1.equals(s3);是true;String s4=new String( "asdf ");是又创建一个对象在堆空间,s3==s4也是false