简析Java中“==”与equals的区别
因为之前在一些书上看到过有关的内容,个人觉得比较有趣,故在这里写一篇文章来表达一下个人的理解与看法。如有不恰当的地方,欢迎大家指出!
好了,话不多说,让我们进入正题吧。
首先,在Java中,“==”是一种操作符,而equals是一种方法。并且equals是直接来源于最初的object类。

从上图中我们可以看到equals方法的基本信息,下面来看具体代码:
public boolean equals(Object obj)
{
return (this == obj); //注意:在equals()方法里用的正是 “==”
}
由此我们知道,“ == ”与equals在本质上其实是一样的,都是依靠“==”进行处理。
这么看好像他们的确是一样的,不要急,让我们来看看下面的代码:
public static void main(String[] args)
{
int t1=11, t2=22, t3=11;
Boolean result1 = (t1==t2); //(11不等于22,false)
Boolean result2 = (t1==t3); //(11等于11,true)
// Boolean result3 = t1.equals(t2);(报错,基本类型不能调用equals方法)
// Boolean result4 = t1.equals(t3);(报错,基本类型不能调用equals方法)
/**
* “equals”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类。如:
* Integer t1 = new Integer(11);
* Integer t2 = new Integer(22);
* Integer t3 = new Integer(11);
* 此时:
* result5 = t1.equals(t2)//(11不等于22,false)
* result6 = t1.equals(t3)//(11等于11,true)
*/
String str1 = "aaa";
String str2 = "aaa";
String str3 = new String("aaa");
Boolean result7 = (str1==str2); //true
Boolean result8 = (str1.equals(str2)); //true
Boolean result9 = (str1==str3); //false
Boolean result10 = (str1.equals(str3)); //true
}
从这段代码中可以看出,当对象是基本数据类型的时候,“==”与equals都是判断基础数据类型的值是否相等。
但是,明明str1、str3的值都是“aaa”,为什么结果会不一样呢?
我们知道,“ == ”是判断变量(栈)内存中存放的对象(堆)的内存地址是否相等,在引用数据类型(如Sring类型)之中,“==”的作用是判断引用数据类型的地址是否相等。
很明显,str1与str3的地址是不一样的,因此“ == ”的结果为false;
但是为什么同样是用了“==”的equals的结果却为true呢?
其实,这里用的equals方法已经不是原来object类中的方法了,而是经过String类重写后新的equals方法,下面给出重写后的代码:
public boolean equals(Object anObject)
{
if (this == anObject)
{
return true;
}
if (anObject instanceof String)
{
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length)
{
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0)
{
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
从代码的第五行(即第二个if语句)中使用了instanceof关键字进行了对象类型的判断,也正是这里将equals方法从原方法改写为“比较两个String类变量的值”
在String中我们可以使用“==”比较地址值,所以再使用equals方法比较地址值意义不大,很多时候我们需要比较的是String具体的内容。所以String类中就进行了equals方法重写。String中重写之后的equals方法比较的就是具体的内容是否相同。
事实上,细心的朋友会发现,Object中的某些子类如数值包装类(Integer, Character, Double, Float等)、Data、File,它们也重写了Object类原有的equals方法,将其改为对比对象的内容,而不是空间地址。
当然!根据不同的需求,我们也可以给equals()赋予新的意义,此时只需要将equals方法重写即可。
最后,整理可得:
对于“==”
基本类型:比较的是值是否相同。
引用类型:比较的是地址值是否相同。
对于equals
只能比较引用类型。默认情况下,比较的是地址值是否相同。
大多数情况下都会被重写。(也包括使用者自己重写)