Object --> Java中使用了单根结构 --> 所有的类都是继承自Object.
对于任何类,都是继承自Object. 不需要显式的写:extends Object. 通过多态的时候知道任何的对象变量都可以存储该对象类以及扩展类的对象。Object object = new Employee(); 然而做了这样一层转换之后,object失去了其的类型信息,当需要真正使用对象时需要进行显式的类型转换。Employee employee = (Employee)object;
1:equals
1)满足自反性: x.equals(x) 一定要返回true.
2)满足对称性: 若x.equals(y)返回true,那么y.equals(x)一定要返回true.
3)满足传递性: 若x.equals(y), y.equals(z)都返回true,那么x.equals(z)一定返回true.
4)满足非空性: x.equals(null)一定返回false.
里氏替换原则:一个子类的实例应该能够替换任何其超类的实例.
public class Employee{ public String getName(){ return name; } public void setSalary(double salary){ this.salary = salary; } @Override public boolean equals(Object otherObj){ if(this == otherObj) return true; if(otherObj == null) return false; if(getClass() != otherObj.getClass()) return false; Employee other = (Employee)otherObj; return name.equals(other.name) && salary == other.salary; } private String name; private double salary;}public class Manager{ public void setBonus(double bonus){ this.bonus = bonus; } @Override public boolean equals(Object otherObj){ if(super.equals(otherObj)){ Manager otherManager = (Manager)otherObj; return bonus == otherManager.bonus; } return false; } private double bonus; }
其中:
1. 判定是否两个对象变量指向的是相同的对象。如果是直接返回true. 否则返回false.
2. 判定另外一个对象是否为空,如果是空,那么返回false.
3. 判定是否其状态能和另外一个对象一致.
但是其中违反了里氏替换原则:
1、Employee对象中只需要name,salary相同,那么认定该两个对象相等。然而现在有一个manager对象的name,salary的内容与一个Employee对象的内容相等,然而无法相当,因为class不相同。
2、违反了我们的忽略内部实现的相等原则:假定有两个set,一种是HashSet 另外一种是TreeSet,两者在实现上是不同,但是可以在内容上相同。但是基于上面的代码无法实现出来equals相等的方法。(因为Class不想等)
所以有些程序员提出来:使用instanceof代替getClass()判断类信息的部分。然而如果使用instanceof进行判断的话,对于上面的第一种情况有不满足交换率,因为Manager对象instanceof Employee,然而Employee instanceof Manager 必然是失败的。正是由于上述的原因,对于equals方法,我们是根据需要做出两种选择:
1. 如果判定相等的场景是在各个实际的类实例中,那么使用getClass来进行判断。 Employee <--- Manager.
2. 如果判定相等的场景是在各个实际类的父类中,那么使用instanceof来进行判断。AbstractSet. = TreeSet OR HashSet
Object本身的实现是:当前对象引用和显式对象引用指向的是同一个对象,那么返回true,否则返回false.
当子类对父类的equals方法进行了覆盖,一般来讲都需要将该类的hashCode方法进行覆盖。因为很可能将该类的放置到各种容器中,而容器中定义产品内容是否相等是依据于hashCode的值。
也就是说: 若x.equals(y)返回true,那么x.hashCode() == y.hashCode();
对于equals方法的参数一定是Object,有很多人会误写方法,导致覆盖方法不成功。在J2SE5之后,加入了注解机制。在方法的头部加入@Override保证覆写动作能够成功的实现。
2:hashCode
所谓的hashCode方法也就是获得该对象的一个hash值,这个是为了在某些容器中进行快速的检索加入进来的一个方法。其返回一个整型的数字。其中根据对象的内容经过算法最后得到一个整型值,对于这个算法的要求是:内容不想等的hash码巨大概率上是不一样的,对于内容相当的对象的hash码,保证该整数值是相等的。
Object本身的实现:是对象变量引用对象的地址的一个算法计算出来的整数。如果没有对hashCode覆盖,那么hashCode的内容认为是该对象变量存储对象的地址。
3. toString
toString方法就是返回一个字符串能表示该对象(很多实现都是使用类名[字段的数值来表示]).这个字符串应该是人可以比较阅读,能够比较方便的表示出当前对象的状态.
toString方法对于日志记录系统的使用十分方便。对于 "" + x(结果是调用x.toString()得到字符串,然后再和空字符串链接起来).
Object本身的实现:返回的类名@hashCode. Java API推荐所有的子类都要覆写toString()方法.