首页 > 代码库 > ==和equals

==和equals

    前两天偶然听到关于==和equals的讨论,编程中也经常用这两种,仔细一想,理解有限,所以稍作分析,要了解这两个的区别,首先要知道内存中的堆和栈,如下图:

    

    基本类型的变量名和值、对象的地址存放在空间较小的栈中,对象内容存放在空间较大的堆中。

==和equals区别

    equals的定义

    要知道equals的作用,首先要知道JAVA中“万象之宗”的Object,Object中声明了equals及实现,查看API文档,发现最主要的一段内容:

    The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

    也就是说当x和y均指向相同的对象时,即栈中保存的值相同时,x.equals(y)才为true。

    equals的例外

    虽然所有对象默认继承自Object,但是部分类重写了Object的equals,如String、Math,来看一下String的equals定义:

    Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.

    在String中,equals被重写,实现变为:当对象x和y的字符序列相同时,则x.equals(y)为true,不再比较x和y对象的地址。

    ==的定义

    使用"=="比较变量时,比较的是变量在栈中保存的值。专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相当,只能用==操作符。

简单实例

    分别测试:

  • 引用类型dog的==和equals
  • 使用构造器的String的==和equals
  • 不使用构造器的String的==和equals

    代码

public class testEquals
{
	public static void main(String []args)
	{
		dog aDog=new dog( );
		dog bDog=new dog( );
		//测试对象类型dog的==
		if(aDog==bDog)
		{
			System.out.println( "aDog==bDog?true");
		}
		else {
			System.out.println( "aDog==bDog?false");
		}
		//测试对象类型的equals
		if ( aDog.equals( bDog ) )
		{
			System.out.println( "aDog.equals( bDog )?true");
		}
		else {
			System.out.println( "aDog.equals( bDog )?false");
		}
		//测试String对象的==
		String s1=new String( "i am a string");
		String s2=new String( "i am a string");
		if ( s1==s2 )
		{
			System.out.println( "s1==s2?true");
		}
		else {
			System.out.println( "s1==s2?false");
		}
		//测试String对象的equals
		String s3=new String( "i am a string");
		String s4=new String( "i am a string");
		if ( s3.equals(s4) )
		{
			System.out.println( "s3.equals(s4) ?true");
		}
		else {
			System.out.println( "s3.equals(s4) ?false");
		}
		//测试基础类型String的==
		String s5="123";
		String s6="123";
		if ( s5==s6 )
		{
			System.out.println( "s5==s6?true");
		}
		else {
			System.out.println( "s5==s6?false");
		}
		//测试基础类型String的equals
		String s7="456";
		String s8="456";
		if ( s7.equals(s8) )
		{
			System.out.println( "s7.equals(s8)?true");
		}
		else {
			System.out.println( "s7.equals(s8)?false");
		}
	} 
}

    测试结果

aDog==bDog?false
aDog.equals( bDog )?false
s1==s2?false
s3.equals(s4) ?true
s5==s6?true
s7.equals(s8)?true

简单分析

  • dog为引用类型,当使用==比较时,比较的是两个对象在栈中保存的地址,所以为false。
  • dog为引用类型,当使用equals时,默认采用Object的equals,比较的是两个对象的引用地址,所以仍然为false。
  • 当String采用构造器的方式,使用==比较时,比较的仍然是两个对象在栈中保存的引用地址,所以为false。
  • 当String采用构造器的方式,使用equals时,因为String重写了equals方法,比较的是两个对象中保存的值,所以此时为true。
  • 当String不使用作基本类型使用时,比较的均为在栈中保存的值,所以都为true。

总结

    一句话总结,==比较的是在栈中保存的内容(地址或值),而equals在默认状态下比较的也是保存在栈中的内容,但是有些类重写了equals方法,比较的是堆中的内容。