zoukankan      html  css  js  c++  java
  • 重写Object.equals()方法和Object.hashCode()方法

    参考文献:

    Java:重写equals()和hashCode()

    为什么重写equals方法,一定要重写HashCode方法?

    重写equals和hashCode

    《CoreJava I 8》第5.2节——Object:所有类的超类。

    正文

    代码示例

    View Code
    package v1ch05.EqualsTest;
    
    import java.util.*;
    
    /**
     * This program demonstrates the equals method.
     * @version 1.11 2004-02-21
     * @author Cay Horstmann
     */
    public class EqualsTest
    {
       public static void main(String[] args)
       {
          Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
          Employee alice2 = alice1;//alice1和alice2同引用
          Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);//alice3与alice1的数据内容相同。
          Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1);
    
          System.out.println("alice1 == alice2: " + (alice1 == alice2));//因为两者同引用,因此使用“==”返回true
    
          System.out.println("alice1 == alice3: " + (alice1 == alice3));//两者不同引用,栈地址不相等,但是堆内存中的数据内容相等,因此"=="为false
    
          System.out.println("alice1.equals(alice3): " + alice1.equals(alice3));//Employee重写equals方法,因此返回true
    
          System.out.println("alice1.equals(bob): " + alice1.equals(bob));//两者数据内容不同,因此为false
    
          System.out.println("bob.toString(): " + bob);//Employee重写了toString()
    
          Manager 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));//因此数据域bonus不相等,所以返回false
          System.out.println("alice1.hashCode(): " + alice1.hashCode());//可以看到alice1与alice3的hashCode是相等的。
          System.out.println("alice3.hashCode(): " + alice3.hashCode());
          System.out.println("bob.hashCode(): " + bob.hashCode());//bob和carl的hashCode则不相等。
          System.out.println("carl.hashCode(): " + carl.hashCode());
       }
    }
    
    class Employee
    {
        //构造函数,姓名,薪水,入职的年,月,日。
       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;
       }
    
       //重写equals方法
       public boolean equals(Object otherObject)
       {
          // 判读当前对象与传入进来的对象是否同引用,如果是则返回true,Object也是进行这样的判断
          if (this == otherObject) return true;
    
          // 如果传入的对象时null则返回false
          if (otherObject == null) return false;
    
          // 如果当前对象和传入的对象不属于同一个类,那么直接返回false
          if (getClass() != otherObject.getClass()) return false;
    
          // 到此我们可以确定传入的对象是一个非空的Employee类,因此可以进行类型转换
          Employee other = (Employee) otherObject;
    
          // 检测数据域是否相等,当所有数据域相等时返回true
          return name.equals(other.name) && salary == other.salary && hireDay.equals(other.hireDay);
       }
    
       // 因此重写了equals方法,所以必须重写hashCode方法,因此必须保证如果两个对象是equal的,那么那么他们的hashCode就必须是相等的。
       // 在类似Hashtable这样的数据结构中,就是通过hashCode来进行判断对象是否相等的,如果不重写hashCode,那么在Hashtable这样的数据结构中
       // 即使两个对象equal,它也会因为hashCode不同而错误得认为对象不相等。
       public int hashCode()
       {
          return 7 * name.hashCode() + 11 * new Double(salary).hashCode() + 13 * hireDay.hashCode();
       }
    
       public String toString()
       {
          return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay
                + "]";
       }
    
       private String name;
       private double salary;
       private Date hireDay;
    }
    
    class Manager extends Employee
    {
       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)
       {
          // 因为Manager是Employee的子类,所以可以先调用父类的equals方法进行比较
          // 如果父类的equal返回false,则直接返回,如果返回true,则在进行子类数据域的相等检测。
          if (!super.equals(otherObject)) return false;
          Manager other = (Manager) otherObject;
          // 检测子类Manager新增数据域是否相等,如果相等则返回true
          return bonus == other.bonus;
       }
    
       public int hashCode()
       {
          return super.hashCode() + 17 * new Double(bonus).hashCode();
       }
    
       public String toString()
       {
          return super.toString() + "[bonus=" + bonus + "]";
       }
    
       private double bonus;
    }
  • 相关阅读:
    优化SQL查询:如何写出高性能SQL语句
    提高SQL执行效率的16种方法
    Spring Ioc DI 原理
    java内存泄漏
    转:js闭包
    LeetCode Best Time to Buy and Sell Stock III
    LeetCode Best Time to Buy and Sell Stock with Cooldown
    LeetCode Length of Longest Fibonacci Subsequence
    LeetCode Divisor Game
    LeetCode Sum of Even Numbers After Queries
  • 原文地址:https://www.cnblogs.com/xwdreamer/p/2497229.html
Copyright © 2011-2022 走看看