要么读书,要么旅行,身体和心灵总有一个要在路上。——罗马假日
咱今天学习的是Java的Object类,首先先看代码,类里面有哪些方法。
咱今天学习两个方法,分别是hashCode,equals。
Object中的hashCode方法就是根据一定的规则与对象相关的信息映射成一个数值,这个数值称为散列值。
public native int hashCode();
这时有个关键字native,Java平台有个用户和本地C代码进行交互操作的API,称为Java Native Interface(简称为JNI)。
Object中的equals方法是用来比较两个对象是否相等的,即object1.equals(object2)为true,则表示object1和object2实际上是引用的同一个对象,但是我们大部分时候进行的是两个对象值的比较,而非地址的比较,所以这个时候,Object的equals方法就不行了。
这时候有的小哥哥要说不对啊,我们平常也使用了String,Integer,Long类型也进行了equals比较啊,他是比较的值,而非地址,你这不会瞎扯淡吧。
不慌不慌,咱慢慢看,先上代码看一下,如果是String类型,使用equals是不是比较的值。
public class Test {
public static void main(String[] args){
String str1="abc";
String str2="abc";
System.out.println(str1.equals(str2));
}
}
咱运行下代码,会发现的确打印的true,说明是比较了str1和str2的值。因为在上篇我们说过了str是一个常量,每次的string类型的数据的地址都是不一样的,不明白的可以移步上篇,https://blog.csdn.net/qq_33774822/article/details/82757055,那不打脸了吗。
开玩笑,怎么可能打脸呢,那咱来看一下这个为什么呢
原来啊,是String类里面重写了equals方法,980行到994行之间就是对两个string类型数据的比较。感谢Java粑粑,这时候是不是应该响起一首歌,你还要我怎样,要怎样。
但是这是常见的类型,那比如我们自定义了一个对象类型,要比较两个对象是否相等,那该怎么做呢,应该是重写equals方法,这里说明一下,如果两个对象通过equals来比较返回的是true,就说明这两个值相等,那么这两个对象的hashCode也应该返回相同的值。这是hashCode的常规规定,咱必须得遵守呢。
hashCode还有一个规定就是在程序运行时,同一对象多次调用hashCode方法应该返回相同的值。
基于以上的两个规定,我们自定义了一个Person类,里面有id,name,还重写了equals和hashCode方法。
上代码咯:
public class Person {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Person)) {
return false;
}
Person person = (Person) o;
return person.getId().equals(id) && person.getName().equals(name);
}
@Override
public int hashCode() {
int result = 17;
result = result * 31 + name.hashCode() + id.hashCode();
return result;
}
}
这里要重点说明一下重写hashCode的时候,用的是31来乘以result,这是为了让产生的hashCode唯一。
主要的原因有两个:
1.更少的乘积结果冲突。31是质数中不大不小的存在,如果使用如3这样比较小的质数,那么得出的乘积会在一个很小的范围内,很容易造成哈希值冲突。如果选择100以上的质数,得到的哈希值会超过int的最大范围。所以这两种都不适合。
2.31可以被JVM优化,31=2<<5-1,JVM可以自动识别为位运算。