java中equals方法

Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中, 这个方法将判断两个对象是否具有相同的引用。如果两个对象具有相同的引用,它们一定是相同的。从这点上看,将其作为默认操作也是合乎情理的。然而, 对于多数类来说,这种判断并没有什么意义。所以当用户自定义一个类时,通常需要重写equals方法,相应地,重写hash Code方法和toString方法也是必要的。

java语言规范要求equals方法具有下面的特性:
(1)自反性:对于任何非空引用x,x.equals(x)应该返回true;
(2)对称性:对于任何引用x,和y,当且仅当,y.equals(x)返回true,x.equals(y)也应该返回true;
(3)传递性:对于任何引用x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true;
(4)一致性:如果x,y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果;
(5)对于任意非空引用x,x.equals(null)返回false;

下面给出编写一个完美的equals方法的建议:

1,将equals的Object类显式参数命名为otherObject。  

2,检测otherObject是否与this引用自同一个对象。

3,检测otherObject是否为null,是的话返回false。

4,检测this与otherObject是否属于同一个类,这里需要注意的情况就是当比较的两个对象不属于同一个类时,比如p.equals(e),p是一个Person,e是一个Employee,

Employee继承自Person。Person拥有name,age私有域,Employee具有occupation域。

如果相等的概念时对象的所有域必须相等,p.equals(e)中使用e instanceof Person返回true,但是如果e.equals(p)调用,p instanceof Employee则返回false,不满足对称性

要求,所以这里需要强制采用getClass来进行检测。

5,将otherObject转换为this类型的变量。

6,现在开始进行私有数据域的比较,对于基本类型如数值,字符和布尔类型使用==进行比较,对对象域使用equals进行比较,所有域都相同则返回true。

7,使用@Override声明有助于错误检查。

public class Employee
{
   private String name;
   private double salary;
   private Date hireDay;

   public Employee(String n, double s, int year, int month, int day)
   {
      name = n;
      salary = s;
      GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
      hireDay = calendar.getTime();
   }

   public String getName()
   {
      return name;
   }

   public double getSalary()
   {
      return salary;
   }

   public Date getHireDay()
   {
      return hireDay;
   }

   public void raiseSalary(double byPercent)
   {
      double raise = salary * byPercent / 100;
      salary += raise;
   }

   public boolean equals(Object otherObject)
   {
      // a quick test to see if the objects are identical
      if (this == otherObject) return true;

      // must return false if the explicit parameter is null
      if (otherObject == null) return false;

      // if the classes don't match, they can't be equal
      if (getClass() != otherObject.getClass()) return false;

      // now we know otherObject is a non-null Employee
      Employee other = (Employee) otherObject;

      // test whether the fields have identical values
      return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
   }

   public int hashCode()
   {
      return Objects.hash(name, salary, hireDay); 
   }

   public String toString()
   {
      return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay
            + "]";
   }
}
public class EqualsTest
{
   public static void main(String[] args)
   {
      Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
      Employee alice2 = alice1;
      Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);
      Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1);

      System.out.println("alice1 == alice2: " + (alice1 == alice2));

      System.out.println("alice1 == alice3: " + (alice1 == alice3));

      System.out.println("alice1.equals(alice3): " + alice1.equals(alice3));

      System.out.println("alice1.equals(bob): " + alice1.equals(bob));

      System.out.println("bob.toString(): " + bob);

      Employee carl = new Manager("Carl Cracker", 80000, 1987, 12, 15);
      Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);
      boss.setBonus(5000);
      System.out.println("boss.toString(): " + boss);
      System.out.println("carl.equals(boss): " + carl.equals(boss));
      System.out.println("alice1.hashCode(): " + alice1.hashCode());
      System.out.println("alice3.hashCode(): " + alice3.hashCode());
      System.out.println("bob.hashCode(): " + bob.hashCode());
      System.out.println("carl.hashCode(): " + carl.hashCode());
   }
}
运行之后:

alice1 == alice2: true
alice1 == alice3: false
alice1.equals(alice3): true
alice1.equals(bob): false
bob.toString(): equals.Employee[name=Bob Brandson,salary=50000.0,hireDay=Sun Oct 01 00:00:00 CST 1989]
boss.toString(): equals.Manager[name=Carl Cracker,salary=80000.0,hireDay=Tue Dec 15 00:00:00 CST 1987][bonus=5000.0]
carl.equals(boss): false
alice1.hashCode(): -1252606650
alice3.hashCode(): -1252606650
bob.hashCode(): -223951770
carl.hashCode(): -785515519
注意这里carl.equals(boss)返回值是false,这是因为在equals方法中

if (getClass() != otherObject.getClass()) return false;
因为carl属于Employee类,而boss属于Manager类,所以不同,当上述代码被注释掉之后,便返回false,这启示我们在重写equals方法时要注意类的判断。

同时可以看出,类中增加了toString方法十分方便。

子类equals的参考写法

package equals;

public class Manager extends Employee
{
   private double bonus;

   public Manager(String n, double s, int year, int month, int day)
   {
      super(n, s, year, month, day);
      bonus = 0;
   }

   public double getSalary()
   {
      double baseSalary = super.getSalary();
      return baseSalary + bonus;
   }

   public void setBonus(double b)
   {
      bonus = b;
   }

   public boolean equals(Object otherObject)
   {
      if (!super.equals(otherObject)) return false;
      Manager other = (Manager) otherObject;
      // super.equals checked that this and other belong to the same class
      return bonus == other.bonus;
   }

   public int hashCode()
   {
      return super.hashCode() + 17 * new Double(bonus).hashCode();
   }

   public String toString()
   {
      return super.toString() + "[bonus=" + bonus + "]";
   }
}

参考自Java核心技术。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值