在最初学习Java时候,经常会看到类似于“==”和equals()的比较这种说法,那时候,不知道在哪里听到的说法是,一个比较地址一个比较值。。。,显然这个说法是极其不严谨的,回过头,重新深入学习才发现了其中猫腻。
显而易见,要说最明显的区别那就是:
“==”是运算符,“equals()“这是方法,当然这种比较是没有太大意义的。下面就好好分析一下这两者的异同吧!
其实,在Java语言中,并没有给出关于equals()方法的具体实现,因为该方法是定义在Object类中的,由于java中所有的类都默认继承于Object,所以所有的类都有这个方法。所以他具体的作用是根据具体的业务逻辑来定义的。但也不妨看看它在Object里面到底是如何定义的:
没错,就只有这三行,很明显,默认的equals方法实现是与“==”操作一样的。所以equals具体的作用是由你自己而定的,通过重写,来定义满足何种条件了,这个equals返回true,或者返回false。比如在String类中,就重写了equals方法,先通过“==”判断是否为一个引用,若“==”返回false,那么继续判断“值”是否相等,若相等,则返回true。源码如下:
再看“==”,“==”这是一个二元运算符,常用于比较原生类型,简单说就是比较值类型,譬如int char之类。也不难理解,equals是方法啊,大多数情况下,对象才能调用方法,int.equals()显然是不可能的。如果“==”返回true,说明两个引用指向的地址相同。
下面通过代码进一步分析:
我们可以很清楚的看到:test1.equals(test2)返回true了,因为上面说了String类equals方法的实现规则了,当两个对象地址不一样时,比较值,如果值相等,则返回true。故此。test1.equals(test3)也返回true,这是为什么呢?因为在String类中,有常量池的存在,当new String("abc");结束后,将在栈中定义一个对象test1,并在堆内存中中开辟一块空间,将内存空间的引用赋值给test1,因为“abc”是字符串常量,所以就会去字符串常量池查看是否有abc字符串对象,没有的话分配一个空间存放abc,并且将其空间地址存入堆中new出来的空间中。然后到String test3 = "abc";在栈中定义test3,也是去字符串常量池中查找是否有此对象,结果是有的,所以直接把abc的地址赋给test3。这样看来两个地址是不一样的,但引用类型的值是相等的,所以很明显13行(“==”)输出false,11行(“equals”)输出的是true。14行输出false也是理所当然了,很明显new了两个对象,地址是不同的。
总结:
- “==”常用来比较原生类型,判断两个变量或实例是不是指向同一个内存空间 ;“equals()”常用来检测对象的相等性
- equals的具体检测规则,由业务逻辑具体实现。如果没有重写equals,那么和“==”将无异!(常见的比如字符串的比较)