通过上面的讲解,相信你已经知道 == 和 equals() 的区别了:一个的比较规则是定死的,一个是可以由编程人员自己定义的。
可是为什么会有 equals() 方法, 而且还可以被自由定制呢?
这个问题要落到Java语言的核心 —— 面向对象思想了。
Java 不同于面向过程的C语言,Java是一款面向对象的高级语言。如果是面向过程编程,直接操作内存上存储的数据的话,用 == 所定义的规则来判断两个数据是否相等已经足够了。
而Java中万物皆对象,我们经常要面临的问题是这两个对象是否相等,而不是这两串二进制数是否相等,仅有 == 是完全不够用的。
由于Java程序员们会创建各种满足它们业务需求的对象,系统无法提前知道两个对象在什么条件下算相等,Java干脆把判断对象是否相等的权力交给编程人员。
具体的措施是:所有的类都必须继承 Object 类,而 Object 类中写有equals()方法。编程人员可以通过重写 equals() 方法来实现自己的比较策略,也可以不重写,使用Object类的equals()比较策略。
//Object类中的equals()方法源码
public boolean equals(Object obj) {
return (this == obj);
}
从 Object 类的 equals() 源码可以看到,如果编程人员没有显示地重写 equals() 方法,则默认比较两个引用是否指向同一个对象。
补充: 关于基本数据类型包装类的比较
由于 Java 中万物皆对象,就连基本数据类型也有其对应的包装类,那么它们对应的比较策略是什么呢?
public static void main(String[] args) {
int a = 3;
Integer b = new Integer(3);
System.out.println(b.equals(a)); //true, 自动装箱
}
从上面的代码可以看到尽管两个引用不同, 但是输出的结果仍为 true, 证明 Integer 包装类重写了 equals() 方法,追踪其源码:
//Integer类中的equals方法
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
从源码看到,基本类型包装类在重写equals()后,比较的还是基本数据类型的值。
结束
通过探索 == 和 equals() 的区别,我们摸清楚了二者别后的比较策略,同时也对 Java 中 equals() 方法的设计进行了思考,相信大家在今后的 Java 编程实战中不会再为相等判断而烦恼了。