JAVA 为什么要重写equals 方法才能对一个值进行操作(容器)

import java.util.*;

public class BasicContainer {
public static void main(String[] args) {
Collection c = new HashSet();
c.add("hello");
c.add(new Name("f1","l1"));
c.add(new Integer(100));

c.remove("hello");
c.remove(new Integer(100));
System.out.println
(c.remove(new Name("f1","l1"))); //如果我下面没重写Object的equals方法为什么不能修改Name的值??
System.out.println(c);
}

}

class Name /*implements Comparable*/ {

private String firstName,lastName;

public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String toString() {
return firstName + " " + lastName;
}

public boolean equals(Object obj) {
if (obj instanceof Name) {
Name name = (Name) obj;
return (firstName.equals(name.firstName))
&& (lastName.equals(name.lastName));
}
return super.equals(obj);
}
public int hashCode() {
return firstName.hashCode();
}
}

c.remove() 方法是根据参数对象去容器里面查找相等的对象,进行删除操作。而相等的依据就是用equals方法和hashCode方法。如果你的Name类不重写equals方法,就会用Object的equals方法去比较。Object本身的hashCode()方法每new一个hashCode都不一样,所以在容器里找不到你要删除的对象(虽然值一样)。
所以你必须重写equals方法根据对象的属性值来判断两个对象是否相等。追问

public boolean equals(Object obj) {

这里传进来的是哪个Name ?

c.add(new Name("f1","l1")); 这个 ? 还是

System.out.println
(c.remove(new Name("f1","l1"))); 这个 ?

基础不是很好

温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-11-20
查API文档,它是这样说的The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true). 翻译过来意思就是:Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。
所以object的equal方法只有被重写之后才能比较这两个对象的“内容”是不是相同,而不是比较是不是同一个对象。显而易见,楼主的这段程序不重写Object方法比较的两者是不是同一个Name对象 当然就不能remove成功了。所以就有当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

我初学容器的时候也有同样的疑惑,建议楼主多查API文档,加油,祝你成功!追问

public boolean equals(Object obj) {

这里传进来的是哪个Name ?

c.add(new Name("f1","l1")); 这个 ? 还是

System.out.println
(c.remove(new Name("f1","l1"))); 这个 ?

基础不是很好

追答

当然是调用remove方法时的了,因为你要移除c.add(new Name("f1","l1")) 这个生成的Name。所以你要调用equal比较再生成一个Name比较两个内容是否相同:c.remove(new Name("f1","l1"))); (这里的new Name是新生成的)

第2个回答  2011-11-20
你说的什么意思??什么叫你能修改name值?建议你去看看object的equals方法:public boolean equals(Object obj),所有类都默认继承object类,也就是name类继承了object的equals方法,此equals方法内部不可能知道name类的firstName、lastName属性,更不可能去判断firstName、lastName属性是否正确了。追问

public boolean equals(Object obj) {

这里传进来的是哪个Name ?

c.add(new Name("f1","l1")); 这个 ? 还是

System.out.println
(c.remove(new Name("f1","l1"))); 这个 ?

基础不是很好

追答

后面那个,在打印对象时默认调用equals方法