Java基础补充 Object类

  • Object类—所有类的直接或间接超类
  • 关于重写equals方法
    • 重写的目的:比较不同对象在状态上是否相等,不局限于是同一个对象
    • 注意参数类型是Object
    • 需满足以下特性
      • 自反性:x.equals(x)为true
      • 对称性:若x.equals(y)为true,则y.equals(x)为true;这是重写equals最需要注意的一点
      • 传递性:若x.equals(y)为true,y.equals(z)为true,则x.equals(z)为true
      • 一致性:多次调用x.equals(y)应返回相同结果
      • 非空性:x.equals(null)为false
    • 是否使用instanceof进行检测?
      如果我们使用instanceof进行检测相等性,那么就允许传入参数是隐式参数类型的子类,此时我们比较的状态是隐式参数类型具有的状态;由于对称性的限制,该子类如果有自己的相等性概念,那么也需要重写equals方法,而这时的equals方法必须允许传入它父类的对象,而又不能考虑子类独有的状态相等性判断,这时矛盾的;举一个具体的例子:看完例子在读一下上边这段话相信就可以理解了

      public class Father {
          private int a;
      
          public Father(int a) {
              this.a = a;
          }
      
          @Override
          public boolean equals(Object obj) {
              if (this == obj) return true; //自反性
              if (obj == null) return false; //非空性
      
              if (obj instanceof Father) {
                  Father objFather = (Father)obj;//强转
                  
                  //进行状态相等性判断
                  if (this.a == objFather.a)return true;
              }
      
              return false;
          }
      }
      public class Child extends Father {
          private int b;
      
          public Child(int a, int b) {
              super(a);
              this.b = b;
          }
          
          @Override
          public boolean equals(Object obj) {
              if (super.equals(obj)) {
                  //进行子类的状态相等性判断
                  if (obj.getClass() == this.getClass()) {
                      Child objChild = (Child)obj;
                      if (this.b == objChild.b)return true;
                  }
                  else return true; //obj是Father类型,由于对称性只能返回true,不能考虑b属性对相等性的影响
              }
              return false;
          }
      }

      一个具体的例子:员工具有名字属性,经理是员工子类,具有名字和奖金属性(实际情况我们会设置主键id比较相等性,这只是个不太恰当但比较好理解的例子)如果员工的equals方法允许传入经理,那么具有相同名字的员工和经理就相等了,无法考虑奖金的因素

    • 是否使用getClass()进行检测?
      如果子类有自己的相等性概念,那么就应该使用getClass()进行检测,这样事情也就变得简单了,不同类对象就是不可能相等
    • 总结instanceof()和getClass()
      • 若子类有自己的相等性概念,使用getClass()
      • 若子类没有自己的相等性概念,由超类决定相等性,使用instanceof
      • 我更偏向于使用getClass(),这会减少很多的麻烦,当然,String这样的final类就随便了哈哈(String源码使用instanceof)
  • 关于hashCode()
    • hashCode()的就是为了散列表而存在的!
    • 一般来说不同的对象(这个相等性的概念应该和equals兼容)具有不同的hash值,但也有可能相同,这取决于方法设计的好坏
    • 大部分情况下使用hashCode()来判断两个对象是否符合相等性的概念是正确的,但无论是否正确,我们都不应该使用,毕竟这不是hashCode()的使命!
  • equals()与hashCode()的兼容问题
    • 如果我们重写了一个类的equals()方法,就要以兼容性的方式重写hashCode()方法,使得 若equals()返回true,则hash值一定相等(当然由于散列冲突equals()返回false时两个hash值也可能相等
    • 虽然在语法层面上没有硬性规定我们要这么做,但出于代码健壮性的角度也需要这么做,防止添加到散列表中时发生让我们费解的情况
  • toString()
    • 以字符串形式返回对象的状态信息,这是个非常有用的调试工具
    • 建议为每个类重写此方法,便于后序调试
  • getClass()
    这是个本地方法,无法重写(我也不会啊),返回调用方法的对象所属类的Class对象

西瓜要挖着吃

一个通往大佬之路的男人

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注