equals 、 ==的深度解析

来源:互联网 发布:知乎神回复2016 知乎 编辑:程序博客网 时间:2024/06/16 13:21

如何理解equals和==之间的区别?


对于刚开始工作的小白,在面试的时候可能经常会遇到下面的代码:

String a= new String("abc");String b= new String("abc"); System.out.println(a==b);System.out.println(a.equals(b));
输出结果如下:
falsetrue
那为什么两个输出结果不一致呢?equals和==到底有什么区别呢?

equals方法


首先,我们来看下equals的源代码equals方法定义在Object类里面,根据具体的业务逻辑来定义该方法,用于检查两个对象的相等性。例如:如果两个User被认定是相等的话,那就意味着他们的每个属性值都是相同的。或许你可以试着在实体类中重写equals方法,然后比较写对象的可等性。equals与hashcode是有契约的,无论什么时候重写equals方法,同样也需要重写hashcode方法。
public boolean equals(Object obj) {return (this == obj);}
通过查看java.lang.Object的源码可知,最原始的equals方法其实就是实现了"=="。但是一般情况下,基于业务的要求我们都需要对实体类中的equals方法进行重写。同样equals与compareTo保持一致也不足为奇,以至于存储对象在TreeMap或TreeSet集合中时,将使用compareTo方法检查相等性,行为是一致的。

= =二元操作符


“==”和“=”在java都中属于二元操作符,通常用于比较基本数据类型的数据和对象。
另外再给大家回顾一下java中的8种基本数据类型:
浮点型float(4 byte), double(8 byte);
整型byte(1 byte), short(2 byte), int(4 byte) , long(8 byte);
字符型:char(2 byte);
布尔型: boolean(实际上对于java虚拟机是不存在这种类型的,boolean类型在编译之后会用0和1来表示,这里不做详细解释)
在进行对象的比较的时候,选择“==”还是使用equals进行比较是一件容易令人头疼的事情。其实说到底"=="就是对比两个对象基于内存的引用,如果两个对象的引用完全相同(即两个引用是指向堆内存中的同一个对象)时,“==”操作将返回true,否则返回false.



==和equals的对比使用



==和equals的主要区别就是:==常用语比较原生类型,而equals方法用于检查对象的相等性。另一个不同的点是:如果==和equals用于比较对象时,当两个引用地址相同时,==返回true。而equals方法返回的值则取决于该对象的equals方法是否重写。
例如字符串的比较,以文章开头的例子为例:

String str1 = new String("hello");String str2 = new String("hello");System.out.println(str1==str2);System.out.println(str1.equals(str2));
第一个输出结果为false,第二个为true;这是因为String中的equals方法被重写了。而这里str1和str2是两个不同的对象,因为在初始化的时候jvm在堆内存中给他们分配了两块不同的内存,所以在他们对应的栈内存中存放的指向内存地址也不相同。因此第一个输出结果是false。
另外在包装类数据对象进行比较时,当你的对比两个引用指向的对象是Object类型的时候,两种比较方式的结果是一致的,因为Object中的equals方法的实现就是"==",即比较内存地址。最后举个栗子:
Object o1 = new Object();Object o2 = new Object();System.out.println(o1 == o2);System.out.println(o1.equals(o2));//这里使o1的引用与o2的引用指向同一个内存地址o1 = o2;System.out.println(o1 == o2);System.out.println(o1.equals(o2));
//输出结果如下:
falsefalsetruetrue

总结

==是比较内存中指向的地址是否相等,equals返回的结果则依赖于所属对象的业务实现,说白了就是看所属对象是否重写了equals方法。换句更加通俗的话来讲:
==比较两个人是否究竟是真正同一个人,equals一般用来比较两个人在逻辑上是否相等(比如规定两人成年之后身高相同就算两人相同等等),想怎么定义就怎么定义,如果不覆盖equals方法的话,默认仍然是比较两人是否同一个人。