大家好,我是Ziph!
让我们来一起轻松区分==和equals的比较!
== 的概念
比较的是变量(栈)内存中存放对象(堆)的地址,用来判断两个两个对象的地址是否相同,也就是说是否指向同一个对象(听起来也许比较晦涩难懂,但是我下面用通俗易懂的说法来给大家解释!)
- 简单来说,== 就是比较的地址是否相同
- 用于比较创建也就是实例化的对象地址,且必须是同一类型
- 比较的结果是true或false
- 还可用于比较两端的变量都代指的数字,比如说:账号假如是int型的,对账号输入的校验就可以用==来比较,因为两端的值都是指向堆中的
equals的概念
equals比较的是两个对象的内容,因为Object类中的equals的默认方法是public boolean equals(Object obj){},而所有的类都隐式的继承与Object类,所以适用于所有对象。如果没有对equals方法进行重写覆盖的话,而Object中的equals方法返回的却是==的判断(也就是比较的地址)
- 简单来说,equals比较的是内容,但是在没有覆盖Object中equals方法的同时,它比较的也是地址
- 用于比较字符串
- 也可以举同样的例子,比如:账号密码是String类型的话,我们就需要用equals来比较了
- 不同字符串的比较
- String s = “Hello”; 这种字符串定义是产生了一个对象存储在字符串池中的
- String s = new String(“Hello”); 虽然看起来都是Hello,但是地址也发生了变化,而这中定义方式,产生了两个对象,一个存储在字符串池中,而另一个存储在堆中
- 然后用equals比较这两种的时候那就是返回false了
注意:== 比equals的运行速度要快,因为只是比较的单纯地址
字符串的比较
/**
* @author Ziph
* @date 2020年2月28日
* @Email [email protected]
*/
public class TestStr {
public static void main(String[] args) {
//特殊字符串的比较
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
System.out.println(str1 == str2); //都产生一个对象且地址内容都相同,返回true
System.out.println(str1.equals(str3)); //内容相同返回true
System.out.println(str1 == str3); //比较的是地址,地址不同则返回false
}
}
那么什么时候需要重写覆盖equals方法呢?
首先覆盖equals方法的应用场景是根据业务需求来定的,比如:(举的栗子通俗易懂,虽然有点长,如果你不明白的话建议去读!)
学生Ziph在学校的端口(学生信息管理系统)存储自己的学生数据,他存储了一遍,有怕没有存上,然后又存储了一遍。那么我们想想,会出现两个Ziph同学的信息吗?而现实中并不会,对吧。
假如说存储了两遍,也就是创建了两个Ziph学生的信息对象,开辟了两块空间,那么我们用equals去校验的时候,只判断了两个对象地址,内容就无法判断了。熟知Java是模拟现实世界解决现实问题,那么这不符合现实啊。这位同学存了两遍,就有两个Ziph同学吗?答案很明显肯定不可能的!
这时候我们就需要重写equals方法了,让他既能判断地址也能判断内容,这就是这个例子中的业务需求!我们以后会根据不同的业务需求去重写equals判断的方法!(而且是经常写!!!)
Object默认equals方法:
//Object类中的默认实现方式
class Object {
public boolean equals(Object obj) {
return (this == obj);
}
}
重写equals方法代码:
/**
* @Author Ziph
* @date 2020/2/28
* @Email [email protected]
*/
public class TestStudent {
public static void main(String[] args) {
//s1和s2地址不同而内容相同
Student s1 = new Student("Ziph", 21, "131000042424249090", 100);
Student s2 = new Student("Ziph", 21, "131000042424249090", 100);
//s1和s3地址不同内容也不同
Student s3 = new Student("Tom", 21, "131000042424249090", 99);
//开始比较
System.out.println(s1.equals(s2)); //true
System.out.println(s1.equals(s3)); //false
}
}
class Student {
private String name; //姓名
private int age; //年龄
private String id; //身份证号码
private double score; //分数
public Student(String name, int age, String id, double score) {
this.name = name;
this.age = age;
this.id = id;
this.score = score;
}
public boolean equals(Object obj) {
//1.比较两个对象的地址是否一样
if (this == obj) {
return true;
}
//2.判断对象不能为空,做的非空判断
if (obj == null) {
return false;
}
//3.确认类型,确认是同一类型,在这个案例中确认是学生对象类型
if (this.getClass() != obj.getClass()) {
return false;
}
//4.转型(转型的前提是类型肯定是Student,也就是说必须是同一类型,在上面已经做过了判断)
//转型的目的就是把obj类型强转为学生类,即:Student类型
Student stu = (Student)obj;
//5.比较内容,假如是内容相同那么我们就认为他们是同一个人
//也就是覆盖后的equals
if (this.name.equals(stu.name) && this.age == stu.age && this.id.equals(stu.id) && this.score == stu.score) {
return true;
}
return false;
}
}