看到这两个词,我以为我掌握了,直到复习时看到ppt中的: 好像哪里有些不对劲! 设想下面的情景:
Person.java public class Person{ private final String name; public Person(String name){ this.name = name; } public String getName(){ return name; } //如果根据名字来判断 //这里的equals()和hashcode()应该怎么写 } Teacher.java public class Teacher extends Person{ private final String title; public Teacher(String name, String title){ super(name) this.title = title; } public String getTitle(){ return title; } //如果将name和title作为判断两个对象是否相等的依据 //这里的equals()和hashcode()应该怎么写 }如果按照ppt中的equals()函数来完成Person类中equals()函数的编写。即:
@Override public boolean equals(Object that){ if (!(that instanof Person)) return false; Person t = (Person)that; return this.name.equals(t.name); }如果客户端这样使用:
Person person = new Person("Li"); Teacher teacher = new Teacher("Li","assistant"); boolean ans1 = person.equals(teacher); //假设已经完成了Teacher.java中的equals()函数 boolean ans2 = teacher.equals(person);自己按照equals()函数"运行"一遍,将会发现ans1是true,但是ans2是false;这显然是有问题的。 因为equals()决定的应该是一个等价关系,即:满足自反,对称,传递。 那问题出在哪里呢? 我们知道,a instanceof B 是判断a是不是B类或者B类子类的一个实例。则 父类 instanceof 子类 得到true; 子类 instanceof 父类 得到false。 ppt中出现的问题,自己还真的没有注意过。每次写到这里都是靠强大的ide自动生成,但是没有仔细看过到底是什么样的。 看了之后,才发现eclipse自动生成用的是getClass()。
用法功能a instanceof B如果a是B类的实例,或者a是B的子类的实例,则返回truea.getClass()==b.getClass()只有当a和b确实是同一个类的实例时,结果才为true结合这个表格,好像使用getClass()更合适一些。stanceof的第一个问题。
第二个问题是类似equals()函数中,参数的引用类型和引用指向的对象类型不同时,instanceof判断使用的是哪个? 结合equals()函数可以很简单的知道,其使用的是引用指向的对象类型。
第二个问题,引出第三个问题:当函数参数的形式类型(即参数声明的类型)和参数对象的实际类型不同时,函数内部什么时候使用对象实际类型?什么时候使用参数声明类型呢? 这个问题,类似重写和重载时究竟调用哪个函数的问题。 编译时便可以确定的,使用声明的引用类型;运行时确定的使用对象实际类型。 最后一个困扰多时的问题,为什么重写equls()函数还要重写hashcode()函数?
1.使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率。 2.保证是同一个对象,如果重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的情况,重写hashcode方法就是为了避免这种情况的出现。