要谈“==”和“equals”的区别,首先要区分是基本数据类型还是引用数据类型。因为基本数据类型没有方法,所以只能谈“==”。对于基本数据类型来说,值相等返回就为true。引用数据类型则不同,因为引用数据类型“==”比较的是变量的引用地址,即为栈地址。引用类型的变量就是String、数组、对象等,如果他指向对象类型的话,就涉及了两块内存,变量存储在栈内存中,对象本身存储在堆内存中。
举个例子,比较一下最基本的类Object。Object的equals返回的就是(this == obj),所以对于Object来说“==”和“equals”实际上是一样的。
在Java中“=”对于基本数据类型来说赋的是基本变量的值,而对于引用数据类型来说,赋的是变量的地址。o1和o2分别占用了两个不同的栈内存,所以“==”的比较结果为false,而o3=o1将o1的栈地址赋给了o3,故o1和o3的“==”比较的结果为true。
所以关于“==”的比较总结起来就是,基本数据类型就是看两个变量的值是否相等,引用数据类型就是看两个变量的引用地址即栈地址是否相等。
而对于equals的比较会相对较为麻烦。因为equals是Object中已经定义的方法。所有类都是继承至Object的,所有类都可以重写这个方法。所以对于equals方法的比较要看实际该类是如何重写这个方法的。
大多数jdk定义的类是对象的属性全部相等equals就返回true,反之则返回false。String对于equals的应用最多,可以专门研究一下。String的equals实现逻辑如下,如果两个变量的引用地址相等,直接返回true。否则判断传参是否是String类型,不是则返回false。否则转成两个char数组,长度以及每个元素进行对比,全部相等则返回true,否则返回false。
总结一下,“==”如果是两个基本数据类型进行比较,只要两个变量的值相等则为true,否则为false。如果是引用数据类型进行比较,则要两个变量只想同一个引用地址才会相等,也就是说其实两个变量实际上是同一个变量(你改变了其中一个变量的属性值,另外一个变量的属性值也会跟着改变),只是变量名不一样而已。对于“equals”的比较就要看该类对其“equals”方法的具体实现了。
所以曾经有一句话说,如果两个变量的“equals”为true,则“==”不一定为true;如果“==”为true,则“equals”一定为true。其实在我看来这句话不算正确的。如果按照java编程规范,这句话是对的,但是规范只是一个约定,约定不一定非得遵从。比如,比如自定义一个类的equals方法中直接return false;那么上面的结论就是错的。“==”和“equals”之间的关系是依据开发者根据实际需求编写的程序逻辑而定的。如果没有重写equals方法,那equals方法和“==”的结果一致。
文章原文来至微信公众号:wanttoknowmore