当你在 程序中遇到判断变量或对象是否相等的情况,想到的应该是用equals或==,两者的区别在哪?先来了解一下内存中的堆和栈。
栈:基本类型的变量和对象的引用变量
堆:实际对象
例如:int i=1;
int j=2;
Object_A a=new Object_A();
注:Object_A a 只是定义了一个变量;new Object_A()创建对象
基本数据类型:
对象内存图:
概括: 基础类型在“栈”中存的是内容值,对象类型在“栈”中存的是地址,而这些地址指向“堆”中的对象。
1、==:比较两个变量所对应的内存中所存储的数值是否相等。
2、equals:用于比较两个独立对象的内容是否相同。
一、基本数据类型
public class TestEquals { public static void main(String[] args){ int a=1; int b=1; int c=2; System.out.println(a==b); //true System.out.println(a==c); //false System.out.println(a.equals(b)); //编译不通过 } } <span style="LINE-HEIGHT: 1.5; FONT-SIZE: 10.5pt"> </span>
小结:
基本数据类型只能用==,比较的是内容;不能用equals。equals被用来对象之间的比较。
二、基本数据类型包装类(Boolean、Integer……)
public class TestEquals {
public static void main(String[] args){
Integer intA=new Integer("123");
Integer intB=new Integer("123");
Integer intC=new Integer("456");
//比较的是地址,intA和intB为不同的对象,故其地址不同
System.out.println(intA==intB); //false
//同上,此对象内容也不同
System.out.println(intA==intC); //false
//比较的是对象的内容
System.out.println(intA.equals(intB)); //true
//对象内容不同
System.out.println(intA.equals(intC)); //false
}
}<span style="BACKGROUND-COLOR: rgb(255,255,255)"><span style="font-family:宋体;"><span style="FONT-SIZE: 12pt"><span style="font-size:18px;"> </span></span><span style="LINE-HEIGHT: 21px">
</span></span></span>
小结:
基础类型包装类的普通类相同,==比较的是对象地址(是否指向同一对象);equals比较的是对象内容。
基础数据和包装类区别:
包装类是对象,拥有方法和字段。当需要往ArrayList,HashMap中放东西时,像int,double这种基本类型是放不进去的,因为容器都是装object的,这是就需要这些基本类型的包装类。
三、普通类
public class TestEquals {
public static void main(String[] args){
Person a=new Person(123);
Person b=new Person(123);
Person c=new Person(456);
//比较的栈中保存的地址
System.out.println(a==b); //false
System.out.println(a==c); //false
//引用类型比较两个对象的引用地址
System.out.println(a.equals(b)); //false
System.out.println(a.equals(c)); //false
}
}
小结:
Person为引用类型,当使用"=="使比较的是栈中地址,所以为false;当使用equals时,默认采用Object的equals,比较的是两个对象所引用的地址,故为false;
四、String、StringBuffer、StringBuilder
情况1:String a="";
public class TestString {
public static void main(String[] args){
String strA="123";
String strB="123";
String strC="456";
//比较内容是否相同,在常量池中只存在一个变量strA的值123,strB直接去用这个值即可
System.out.println(strA==strB); //true
//内容不同
System.out.println(strA==strC); //false
//比较的是内容
System.out.println(strA.equals(strB)); //true
//内容不同
System.out.println(strA.equals(strC)); //false
}
}
常量池/字符串连接池:在JVM内,存在字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率.字符串池由String类维护,我们可以调用intern()方法来访问字符串池。当用“”创建对象时,所创建的对象会加入到字符串连接池里。如果要创建下一个字符串对象,JVM会到字符串池中寻找,
若存在,则共享一个(返回一个已经存在对象的引用给要创建的对象引用)。
不存在,则创建一个新对象(返回一个新对象的对象的引用给要创建的对象引用)。
小结:
"=="和equals:比较的都是内容
情况2:String a=new String();
public class TestString {
public static void main(String[] args){
String strA=new String("123");
String strB=new String("123");
String strC=new String("456");
//比较的两个对象的地址
System.out.println(strA==strB); //false
//地址不同
System.out.println(strA==strC); //false
//比较的是内容
System.out.println(strA.equals(strB)); //true
//内容不同
System.out.println(strA.equals(strC)); //false
}
}
小结:
使用new创建对象,“==”比较的栈中的引用地址;这里的equlas重写了Object中的equals方法,比较的是两个对象中保存的值,所以为true。
总结:
==
比较内容:基本数据类型、String中引号创建对象
比较地址:类(包装类、普通类、String)
equals:
比较内容:包装类和String(重写了Object的equals方法)
比较地址:一般类
==用来比较栈内存中变量值或者对象地址,equals默认情况比较栈内对象地址。包装类、String构造器重写了equals方法后比较的是堆内对象的内容。