import java.util.*;
public class BasicContainer {
public static void main(String[] args){
Collection c=new HashSet();

/*
c.add("hello");
p(c); //output:[hello]
c.add(" lol");
p(c);

c.remove("hello");//每一个对象都必须依次移除,不能在同一remove语句中
p(c);
*/

c.add(new Name("山田","孝之"));
p(c);

//如果新添加了一个对象在与原来的equals时,不一致,则会新添加一个对象
c.remove(new Name("山田","孝之"));
p(c);
//已经remove了 Name对象,所以再打印remove结果为false
p(c.remove(new Name("山田","孝之")));


}
static void p(Object e){
System.out.println(e);
}}class Name{
String fn;
String ln;
Name(String fn,String ln){
this.fn=fn;
this.ln=ln;
}
public String toString(){
return fn+" "+ln;
}
public boolean equals(Object o){
//判断o是不是Name的实例
if(o instanceof Name){
Name obj=(Name)o;
return this.fn==obj.fn&&this.ln==obj.ln;
}
return super.equals(o);      //???
}
//???
public int hashCode(){
return fn.hashCode();
}}return super.equals(o);      为什么要返回给父类?
为什么要改写hashcode???

解决方案 »

  1.   

    1 如果对象o不是Name类,那么就调用父类的equals方法
    2 如果重写了equals方法,那么hashCode方法必须被重写,因为Java源代码的注释中有这样一句话:相同的对象必须有相同的hash code
      

  2.   

    name.equals(obj);如果obj是Name类对象,那么进入if里,做你自定义的判断方法,判断name与obj是否为一个对象如果obj不是Name类对象,那么就使用父类的方法。比如你现在Name没有显示的继承某个类,那么Object就是它的父类,super.equals()调用的就是Object的equals()方法。
      

  3.   

    1) 按照代码的意思
    if(o instanceof Name){
      Name obj=(Name)o;
      return this.fn==obj.fn&&this.ln==obj.ln;
    }
    return super.equals(o);如果o不是个Name实例,那么无法取到o的fn和ln,那么就交给父类(也就是Object)的equals来判断。
    这样写编译运行都没问题,但逻辑上是不必要的。因为父类Object的equals()只有在this==o时才返回true,因此既然o连Name实例都不是,显然不可能有this==o 所以return super.equals(o);是不必要的,可以被return false代替。2) 改写hashCode()是为了能更有效率地被HashSet利用(HashSet的原理可以查具体资料)
    你也可以不改写,则父类Object的hashCode()方法被自动使用,但那不能保证两个equal的Name对象返回同样的hashCode,这样把Name对象添加到HashSet中去会有问题。
      

  4.   

    这道题没有必要return super.equals(o)。只要return false就可以了。hashcode楼上已说明。