zoukankan      html  css  js  c++  java
  • getClass()和instanceof以及类的equals方法

    在比较两个类时,常见有两种做法,一种是x.getClass() == y; 一种是x instanceof y,下面我们来比较这两种做法的区别。

    getClass()返回一个对象所属的类

        public static void main(String[] args)  {
            Hero h1 = new Hero(null,10,2);
            Hero h2 = new Hero("zhang",10,2);
         Superman s1 = new Superman("zhang");
    System.out.println(h1.getClass());
          System.out.println(h1.getClass() == h2.getClass());

          System.out.println(h1.getClass() == s1.getClass());
          System.out.println(s1.getClass() == h1.getClass());

    
        }
    返回:
      class source.Hero

      true
      false
      false

     

    可以看到,getClass返回的是一个类名,也就是说只会在类名相同时返回true,不会判断子类与父类的继承关系。

    instanceof比较一个对象是否是该类的实例

        public static void main(String[] args)  {
            Hero h1 = new Hero(null,10,2);
            Hero h2 = new Hero("zhang",10,2);
            Superman s1 = new Superman("zhang");
    
            System.out.println((h1 instanceof Hero));
            System.out.println(h2 instanceof Superman);
            System.out.println(s1 instanceof Hero);
            System.out.println(h1 instanceof Superman);
        }
    返回:

      true
      false
      true
      false

    可以看到,instanceof会判断继承关系,子对象 instanceof 父类 会返回true,父对象 instanceof 子类会返回 false。 可以理解为判断两个问题:你是这个类吗? 你是这个类的派生类吗?

    equals方法:

        public boolean equals(Object otherObject) {
            if(this == otherObject) return true;
            
            if(otherObject == null) return false;
            
            if(getClass() != otherObject.getClass()) return false;
                    
            Hero other = (Hero)otherObject;
            
            return name.equals(other.name)
                    && hp == other.hp
                    &&damage == other.damage;
        }

    equals方法具有下面特性:

    1,自反性

    2,对称性

    3,传递性

    4,一致性

    5,对于任意非空引用x,x.equals(null)应该返回false。

    下面我们首先结合上面的内容讨论对称性

    father.equals(child)

    这里的father与child具有相同的姓氏,血型,家族。如果在Father.equals中用instanceof检测,会得到true。这意味着如果反过来调用:

    child.equals(father)

    也需要返回true。

    应该这样说:

    1,如果子类拥有自己的相等概念,则对称性需求将强制采用getClass进行检测。 例如雇员和经理,对应的域相等就认为两个对象相等;如果两个经历对应的名字薪水雇佣日期都相等,而奖金不相等,就认为他们不相同。

    2,如果由超类决定相等的概念,那么可以用instanceof进行检测,就可以在不同的子类对象之间进行相等的比较。例如经理是雇员的儿子类,假设使用雇员的ID作为相等的检测条件,那么这个相等概念也适用于经理,此时可以用instanceof进行检测,并且应该将Employee.equals方法声明为final。

     编写完美equals方法的建议(来自CoreJava):

      1,显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量 这里参数一定是Object类型 否则不会产生Override

      2,检测this和otherObject是否引用同一个对象

        

    if(this == otherObject) return true;

      3,检测otherObject是否为null。如果是null,则返回false

      4,比较this和otherObject是否属于同一个类。按照上面红字的总结:如果equals的语义在每个子类中有所改变,就用getClass检测:

    if (getClass() != otherObject.getClass()) return false;

      如果所有的子类都拥有统一的语义,就是用instanceof检测

      

    if (!(otherObject instanceof ClassName)) return false;

      5,将otherObject转换为相应的类类型变量:

    ClassName other = (ClassName) otherObject;

      6,现在开始对所有需要比较的域进行比较。使用 == 比较基本类型域, 使用equals比较对象域。 

      

    return field 1 == field2
            && Objects.equals(field2,other.field2)
            &&....... ;

      这里需要注意: 如果在两个参数都为null时需要返回true,那么应该使用Objects.equals(1,2)

             如果不能接受有参数为null,或者两个参数不会为null,则使用a.equals(b) (当有一个参数为null时,a.equals(b)将会抛出NullPointerException)

       如果在子类中重新定义equals,就要在其中包含调用super.equals(other)

  • 相关阅读:
    [ASP.NET]c#利用WebClient和WebRequest类获得网页源代码
    远程重启、关闭电脑命令、远程重启计算机命令。
    SQL SERVER 2005转换为SQL2000数据库,生成脚本及导出数据全过程
    Winform,C#,listView判断鼠标点击是行还是listView的空白区
    前端MVC Vue2学习总结(八)——前端路由
    JavaSE学习总结(一)——Java基础
    开区间覆盖的约简
    流形上的微积分 习题 1.18
    王昆扬老师发来的材料:关于实数的构造
    连续函数注记
  • 原文地址:https://www.cnblogs.com/Joey777210/p/11770454.html
Copyright © 2011-2022 走看看