A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 丁岩 中级黑马   /  2012-8-24 09:04  /  2583 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. class HashSetTest
  2. {
  3. public static void sop(Object obj)
  4. {
  5. System.out.println(obj);
  6. }
  7. public static void main(String[] args)
  8. {
  9. HashSet hs = new HashSet();

  10. hs.add(new Person("a1",11));
  11. hs.add(new Person("a2",12));
  12. hs.add(new Person("a3",13));
  13. // hs.add(new Person("a2",12));
  14. // hs.add(new Person("a4",14));

  15. //sop("a1:"+hs.contains(new Person("a2",12)));

  16. // hs.remove(new Person("a4",13));


  17. Iterator it = hs.iterator();

  18. while(it.hasNext())
  19. {
  20. Person p = (Person)it.next();
  21. sop(p.getName()+"::"+p.getAge());
  22. }
  23. }
  24. }
  25. class Person
  26. {
  27. private String name;
  28. private int age;
  29. Person(String name,int age)
  30. {
  31. this.name = name;
  32. this.age = age;
  33. }

  34. public int hashCode()
  35. {
  36. System.out.println(this.name+"....hashCode");
  37. return name.hashCode()+age*37;
  38. }

  39. public boolean equals(Object obj)
  40. {

  41. if(!(obj instanceof Person))
  42. return false;

  43. Person p = (Person)obj;
  44. System.out.println(this.name+"...equals.."+p.name);

  45. return this.name.equals(p.name) && this.age == p.age;
  46. }


  47. public String getName()
  48. {
  49. return name;
  50. }
  51. public int getAge()
  52. {
  53. return age;
  54. }
  55. }
复制代码
毕老师的这段代码我有一点看不懂就是为什么设置
  1. public boolean equals(Object obj)
  2. {

  3. if(!(obj instanceof Person))
  4. return false;

  5. Person p = (Person)obj;
  6. System.out.println(this.name+"...equals.."+p.name);

  7. return this.name.equals(p.name) && this.age == p.age;
  8. }
复制代码
明明在主函数中已经做强制转换了呀,
while(it.hasNext())
  {
   Person p = (Person)it.next();
   sop(p.getName()+"::"+p.getAge());
  }
应该不用判断了呀!
而且毕老师的写的这个函数也没有在这个程序里调用过。这样做是出于什么考虑呢?
望高人相告!!!!!

评分

参与人数 1技术分 +1 收起 理由
杨志 + 1

查看全部评分

3 个回复

倒序浏览
这个很容易理解哦,因为equals接受的参数为Object。所以尽管你知道obj就是Person类型的,但是编译器不知道。
因此需要把obj转成Person,这就是多态的向下转型。
这个问题等你学了泛型后,在主函数中就真的不用转型了。
回复 使用道具 举报
王小刚 发表于 2012-8-24 09:39
这个很容易理解哦,因为equals接受的参数为Object。所以尽管你知道obj就是Person类型的,但是编译器不知道 ...

可是后来我把那个函数删掉了,程序不影响运行呀。
回复 使用道具 举报
丁岩 发表于 2012-8-24 09:58
可是后来我把那个函数删掉了,程序不影响运行呀。
  1. public int hashCode()
  2.         {
  3.                 System.out.println(this.name+"....hashCode");
  4.                 return name.hashCode()+age*37;
  5.         }

  6.         public boolean equals(Object obj)
  7.         {

  8.                 if(!(obj instanceof Person))
  9.                 return false;

  10.                 Person p = (Person)obj;                                                               
  11.                 System.out.println(this.name+"...equals.."+p.name);

  12.                 return this.name.equals(p.name) && this.age == p.age;
  13.         }
复制代码
主函数里的强制转换是为了调用Person类里的方法,获取名字和年龄。
equals()方法,是add()方法隐藏调用的。add()方法返回值是boolean型,因为它先判断哈希值是否相同,不同则返回true,添加成功。如果相同则调用equals()方法进行内容比较。
楼主在hashCode()里已经定义了具体哈希值规则,当姓名、年龄不同时则哈希值不一样,add()返回true。当姓名、年龄都相同时,哈希值相同,则调用Person类中的equals()方法进行内容比较。
equals()方法是继承于Object类的方法,如果不重写的话,比较的是对象的地址值。在add(new Person("a2",12))之后,再来一次add(new Person("a2",12)),前后两个Person是两个对象,虽然长着一样,但他们在堆中的地址是不一样的,所以equals()返回false,导致add()返回true,添加成功,出现两个"a2"12。
只有当重写equals()方法后,自定义比较的规则,才能避免上面的错误。重写方法,格式必须保持一致,在不使用泛型的前提下,equals(Object obj),必须是Object,不能是Person。Object obj=new Person();要想访问Person属性:姓名、年龄,必须强制转换成Person类,所以就有了(Person)obj。不转换的话,p.name和p.age就会编译失败的。
主函数中while()里的p和equals()中的p都是局部变量,没有关系的。



回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马