科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Java语言深入:深入研究Java equals方法

Java语言深入:深入研究Java equals方法

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

java 5之后提供优秀的并发库util.concurrent,.net中缺乏类似的功能。由于硬件体系发生了变化,多核时代来临……

作者:baocl 来源:赛迪网 2007年11月21日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共2页)

是否equals方法比较的两个对象一定是要同一类型?上面我用了"通常",这也是绝大多数程序员的愿望,但是有些特殊的情况,我们可以进行不同类型的比较,这并不违反规范。但这种特殊情况是非常罕见的,一个不恰当的例子是,Integer类的equals可以和Sort做比较,比较它们的value是不是同一数学值。(事实上JDK的API中并没有这样做,所以我才说是不恰当的例子)在完成quick check以后,我们就要真正实现你认为的“相等”。对于如果实现对象相等,没有太高的要求,比如你自己实现的“人”类,你可以认为只要name相同即认为它们是相等的,其它的sex, ago都可以不考虑。这是不完全实现,但是如果是完全实现,即要求所有的属性都是相同的,那么如何实现equals方法?

以下是引用片段:
  class Human{
  private String name;
  private int ago;
  private String sex;
  ....................
  public boolean equals(Object obj){
  quick check.......
  Human other = (Human)ojb;
  return this.name.equals(other.name) && this.ago == ohter.ago && this.sex.equals(other.sex);
  }
  }

  这是一个完全实现,但是,有时equals实现是在父类中实现,而要求被子类继承后equals能正确的工作,这时你并不事实知道子类到底扩展了哪些属性,所以用上面的方法无法使equals得到完全实现。

  一个好的方法是利用反射来对equals进行完全实现:

以下是引用片段:
  public boolean equals(Object obj){
  quick check.......
  Class c = this.getClass();
  Filed[] fds = c.getDeclaredFields();
  for(Filed f:fds){
  if(!f.get(this).equals(f.get(obj)))
  return false;
  }
  return true;
  }

  为了说明的方便,上明的实现省略了异常,这样的实现放在父类中,可以保证你的子类的equals可以按你的愿望正确地工作。关于equals方法的最后一点是:如果你要是自己重写(正确说应该是履盖)了equals方法,那同时就一定要重写hashCode().这是规范,否则.............

  我们还是看一下这个例子:

以下是引用片段:
  public final class PhoneNumber {
  private final int areaCode;
  private final int exchange;
  private final int extension;
  public PhoneNumber(int areaCode, int exchange, int extension) {
  rangeCheck(areaCode, 999, "area code");
  rangeCheck(exchange, 99999999, "exchange");
  rangeCheck(extension, 9999, "extension");
  this.areaCode = areaCode;
  this.exchange = exchange;
  this.extension = extension;
  }
  private static void rangeCheck(int arg, int max, String name) {
  if(arg < 0 || arg > max)
  throw new IllegalArgumentException(name + ": " + arg);
  }
  public boolean equals(Object o) {
  if(o == this)
  return true;
  if(!(o instanceof PhoneNumber))
  return false;
  PhoneNumber pn = (PhoneNumber)o;
  return pn.extension == extension && pn.exchange == exchange && pn.areaCode == areaCode;
  }
  }

  注意这个类是final的,所以这个equals实现没有什么问题。我们来测试一下:

以下是引用片段:
  public static void main(String[] args) {
  Map hm = new HashMap();
  PhoneNumber pn = new PhoneNumber(123, 38942, 230);
  hm.put(pn, "I love you");
  PhoneNumber pn1 = new PhoneNumber(123, 38942, 230);
  System.out.println(pn);
  System.out.println("pn.equals(pn1) is " + pn.equals(pn1));
  System.out.println(hm.get(pn1));
  System.out.println(hm.get(pn));
  }

  既然pn.equals(pn1),那么我put(pn,"I love you")后,get(pn1)为什么是null呢?答案是因为它们的hashCode不一样,而hashMap就是以hashCode为主键的。所以规范要求,如果两个对象进行equals比较时如果返回true,那么它们的hashcode要求返回相等的值。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章