getClass()和instanceof以及类的equals方法

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

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

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());spa

 }
返回:
  class source.Hero

  true
  false
  falsecode

 

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

 

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

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。 能够理解为判断两个问题:你是这个类吗? 你是这个类的派生类吗?get

 

equals方法:io

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方法具备下面特性:class

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)

相关文章
相关标签/搜索