软件构造——equals()和hashcode()你真的会了吗?

看到这两个词,我以为我掌握了,直到复习时看到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的子类的实例,则返回true
a.getClass()==b.getClass() 只有当a和b确实是同一个类的实例时,结果才为true

结合这个表格,好像使用getClass()更合适一些。stanceof的第一个问题。

第二个问题是类似equals()函数中,参数的引用类型和引用指向的对象类型不同时,instanceof判断使用的是哪个?
结合equals()函数可以很简单的知道,其使用的是引用指向的对象类型。

第二个问题,引出第三个问题:当函数参数的形式类型(即参数声明的类型)和参数对象的实际类型不同时,函数内部什么时候使用对象实际类型?什么时候使用参数声明类型呢?
这个问题,类似重写和重载时究竟调用哪个函数的问题。
编译时便可以确定的,使用声明的引用类型;运行时确定的使用对象实际类型。
最后一个困扰多时的问题,为什么重写equls()函数还要重写hashcode()函数?

1.使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率。
2.保证是同一个对象,如果重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的情况,重写hashcode方法就是为了避免这种情况的出现。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章