zoukankan      html  css  js  c++  java
  • 如何正确的覆盖equals和hashCode

    一、Object所有的非final方法

    1. public boolean equals(Object obj)
    2. public native int hashCode()
    3. public String toString()
    4. protected native Object clone() throws CloneNotSupportedException
    5. protected void finalize() throws Throwable { }

    类的方法前加final关键字,说明该方法不能被该类的子类重写。

    二、equals方法和hashCode方法

    1、什么时候需要覆盖equals方法

    如果类具有自己特有的“逻辑相等”概念(不同于对象等同的概念),而且超类还没有覆盖equals以实现期望的行为,这时候我们就需要覆盖equals方法。

    2、如何正确的覆盖equals方法

    equals方法实现了等价关系:自反性,对称性,传递性,一致性,非空性(x.equals(null)返回为false

    • 使用==操作符检查“参数是否为这个对象的引用”,如果是,则返回true。
    • 使用instanceof操作符检查“参数是否为正确的类型”,如果不是,则返回false。
    • 把参数转换成正确的类型。
    • 对于该类中的每个“关键”阈,检查参数中的阈是否与该对象中对应的阈相匹配。
    class Student{
        
        private String name;
        private int age;
        private double height; 
        @Override
        public boolean equals(Object obj) {
            //使用==操作符检查“参数是否为这个对象的引用”
            if(this==obj)
                return true;
            //使用instanceof操作符检查“参数是否为正确的类型”
            if(!(obj instanceof Student))
                return false;
            //把参数转换成正确的类型。
            Student student=(Student) obj;
            //对于该类中的每个“关键”阈,检查参数中的阈是否与该对象中对应的阈相匹配。
            return  this.name==student.name && this.age==student.age && this.height==student.height;
        }
    }

    1、编写完成equals方法之后,应该问自己三个问题:它是否对称的、传递的、一致的。

    2、不要将equals声明中的Object对象替换为其他的类型

    public boolean equals(Student obj)

    这样相当于重载了equals方法,而非是覆盖。

    3、覆盖equals时总要覆盖hashCode

    HashCode有一条约定如下:

    如果两个对象根据equals(Object)方法比较是相等,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。

    下面给出一种简单的解决办法:

    1. 把某个非零的常数值,比如说17,保存在一个名为result的int类型的变量中。
    2. 对于对象每个关键域f(指equals方法中涉及的每个域),完成以下步骤:
      1. 如果该域是boolean类型,则计算(f ? 1 : 0)。
        private boolean flag=true;
        int boolTemp=flag?0:1;
      2. 如果该域是byte、char、short或者int类型,则计算(int)f。
      3. 如果该域是float类型,则计算Float.floatToIntBit(f)。
      4. 如果该域是long类型,则计算(int)(f ^ (f >>> 32))。
      5. 如果该域是double类型
        private double height; 
        long heightBits=Double.doubleToLongBits(height);
        int heightTemp=(int)(heightBits ^ (heightBits >>> 32));
      6. 如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样为这个域递归调用hashCode。
        private String name;
        int stringTemp=this.name.hashCode();

    完整的Student类:

    class Student{
        private String name;
        private int age;
        private double height; 
        @Override
        public boolean equals(Object obj) {
            //使用==操作符检查“参数是否为这个对象的引用”
            if(this==obj)
                return true;
            //使用instanceof操作符检查“参数是否为正确的类型”
            if(!(obj instanceof Student))
                return false;
            //把参数转换成正确的类型。
            Student student=(Student) obj;
            //对于该类中的每个“关键”阈,检查参数中的阈是否与该对象中对应的阈相匹配。
            return  this.name==student.name && this.age==student.age && this.height==student.height;
        }
        
        @Override
        public int hashCode() {
            //初始化
            int result=17;
            //String类型
            result=this.name.hashCode()+result;
            //int类型
            result=this.age+result;
            //double类型
            long heightBits=Double.doubleToLongBits(height);
            int heightTemp=(int)(heightBits ^ (heightBits >>> 32));
            result=heightTemp+result;
            //返回
            return result;
        }
    }
  • 相关阅读:
    oracle2
    oracle1
    oracle1
    Java复习2.程序内存管理
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/lyajs/p/5796865.html
Copyright © 2011-2022 走看看