==和equals的区别是什么?
==比较的是两个对象在内存中的地址,equals比较的是两个对象的值。这个说法是片面的。
==的作用
==是专门用来比较两个变量是否相等的,即比较两个变量在内存中存储的数据值是否相等,比较两个基本数据类型或者两个引用变量是否相等时,只能用==
- 变量:指可以改变的量,是内存中的一个空间(容器),用于存储数据
- 引用变量:当一个变量指向的是对象类型的数据,那这个变量即引用变量
//obj为引用变量,存储的数据为new Object()这个对象在内存中的地址,并不是对象的值
Object obj = new Object();
equals的作用
- Object类中的equals方法在比较是用的还是==,所以如果没有重写equals方法,它将继承Object类中的equals方法,相当于还是在使用==进行比较
//Object类中的equals方法,是用==进行比较
public boolean equals(Object obj) {
return (this == obj);
}
- 对于重写过的equals方法,比较的是两个对象的值,如String中的equals方法
//String源码中的equals方法
public boolean equals(Object anObject) {
//先用==比较,如果内存中的地址一样,则不再进行比较,直接返回true
if (this == anObject) {
return true;
}
//是String类型,才进行以下的比较
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
//通过循环比较字符串中每个字符的值是否相等,不相等则返回false
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
//其他情况则直接返回false
return false;
}
- 对于基本数据类型的包装类,也是重写了equals方法,比较的是对象的值
//以Integer为例,比较的是对象的值,其他基本数据类型的包装类也一样
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
- 自定义对象,如果重写了equals方法,则比较的是每个属性的值是否相等
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.yms.entity;
public class User {
private String name;
private Integer age;
public User() {
}
public String getName() {
return this.name;
}
public Integer getAge() {
return this.age;
}
public void setName(final String name) {
this.name = name;
}
public void setAge(final Integer age) {
this.age = age;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$age = this.getAge();
Object other$age = other.getAge();
if (this$age == null) {
if (other$age != null) {
return false;
}
} else if (!this$age.equals(other$age)) {
return false;
}
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $age = this.getAge();
result = result * 59 + ($age == null ? 43 : $age.hashCode());
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
public String toString() {
return "User(name=" + this.getName() + ", age=" + this.getAge() + ")";
}
}
为什么重写了equals方法就必须重写hashCode方法?
- 在每个覆盖了equals方法的类中,都必须覆盖hashCode方法。如果不这样做的话,就会违反hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这列集合包括HashMap和HashSet。
- 如果两个对象的值相等,那么它们对应的hashCode则一定相等,反过来则不一定,这就是我们所说的哈希冲突
对于equals的其他理解可参考Effective Java 第三版中第10条、第11条
1581

被折叠的 条评论
为什么被折叠?



