equals与“==”之惑

Java中存在两种判断相等的方式,一个采用运算符“==”进行判断,另一个是采用equals方法进行判断。一直对这两种判断方式感到十分迷惑,最近有空好好研究了一番。

==”操作符比较的是两个变量的值是否相等,对于对象的引用则表示的是对象在堆中存储的地址是否相等。

equals方法是Object的一个方法,对于没有重写这个方法的类来说,equals方法的作用和“==”是一样的,因为这个方法就是用“==”来实现的。对于重写了这个方法(Java Api中的绝大部分类也这么做了)的类来说,那么功能就与“==”不同了,一般来说,equals方法表示的是两个引用是否是同一个对象的引用,即比较的是对象的内容是否相同。

下面,分类型来说说“==”与equals方法的用法。

1、  简单基本类型之间的比较

对于简单基本类型之间的比较来说,只能使用“==”运算符,其含义也是显而易见的,就是比较两个值是否相等,在此不多做解释。

2、  简单对象之间的比较

此处的简单对象指的是那些自定义的,但是未重写equals方法的类的实例。对于这类的equals方法的作用是与“==”相同的,比较的是两个对象的地址是否相同。下面是我写的测试代码:

publicclass Test1 {

 

}

 

publicclass Test2 {

    publicstaticvoid main(String[] args) {

      

       Object obj1 = new Object();

       Object obj2 = obj1;

       Object obj3 = new Object();

       System.out.println("obj1 == obj2: " + (obj1 == obj2));

       System.out.println("obj1.equals(obj2): " + obj1.equals(obj2));

       System.out.println("obj1 == obj3: " + (obj1 == obj3));

       System.out.println("obj1.equals(obj3): " + obj1.equals(obj3));

       

       Test1 test11 = new Test1();

       Test1 test12 = test11;

       Test1 test13 = new Test1();

       System.out.println("test11 == test12: " + (test11 == test12));

       System.out.println("test11.equals(test12): " + test11.equals(test12));

       System.out.println("test11 == test13: " + (test11 == test13));

       System.out.println("test11.equals(test13): " + test11.equals(test13));

    }

 

}

输出结果为

obj1 == obj2: true

obj1.equals(obj2): true

obj1 == obj3: false

obj1.equals(obj3): false

test11 == test12: true

test11.equals(test12): true

test11 == test13: false

test11.equals(test13): false

从中可以看出obj1obj2obj1obj3test11test12test11test13的比较结果是一样的,而且equals方法与“==”的比较结果是一样的。

3、  String类型的比较

对于String对象的equals方法比较的就是两个对象的内容是否相同,而“==”比较的依旧是两对象的地址是否相同。

publicclass Test1 {

    publicstaticvoid main(String[] args) {

       String s1 = "Monday";

       String s2 = "Monday";

       String s3 = new String("Monday");

       System.out.println("s1 == s2: " + (s1 == s2));

       System.out.println("s1.equals(s2): " + s1.equals(s2));

      

       System.out.println("s1 == s3: " + (s1 == s3));

       System.out.println("s1.equals(s3): " + s1.equals(s3));

      

       s3 = s3.intern();

       System.out.println("after s3.intern()");

       System.out.println("s1 == s3: " + (s1 == s3));

       System.out.println("s1.equals(s3): " + s1.equals(s3));

    }

}

 

输出结果为:

   s1 == s2: true

   s1.equals(s2): true

   s1 == s3: false

   s1.equals(s3): true

   after s3.intern()

   s1 == s3: true

s1.equals(s3): true

从结果来看,s1s2应该引用的是同一个对象。原因是程序在运行的时候会创建一个字符串缓冲池,当使用String s1 = "Monday"创建对象时,程序会将s1放入到缓冲池中,而再用String s2 = "Monday"创建对象时,程序会首先查找池中的对象是否存在相同值的,如果存在,就返回池中对象的引用,不存在,则新建一个对象放入池中,并返回对象,这里显然返回的是s1创建的对象的应用,因此,第一行结果为true。又因为Stringequals方法比较的是内容,所以第二行的结果也是true。当使用String s3 = new String("Monday")创建对象时,是告诉程序不使用池中的具有相同内容的对象,直接新建一个对象,因此第三行为false,第四行为true,但是当执行s3.intern()后,程序会检查池中是否存在相同内容的对象,如果存在,则返回该对象的引用,如果不存在,则将对象放入池中,并返回该对象的引用,因此第五行和第六行都是true

 

 

4、  简单基本类型与封装类之间的比较

在这里,以intInteger为例进行说明。在jdk1.5以上的版本中基本类型与封装类型能够互相转化,与String类型的对象和字符串常量之间的比较类似。

测试代码如下:

   publicclass Test1 {

    publicstaticvoid main(String[] args) {     

       int i = 1;

       Integer i1 = 1;

       Integer i2 = 1;

       Integer i3 = new Integer(1);

       Integer i4 = new Integer(1);

      

       System.out.println("i1 == i2: " + (i1 == i2));

       System.out.println("i1.equals(i2): " + i1.equals(i2));

      

       System.out.println();

       System.out.println("i3 == i4: " + (i3 == i4));

       System.out.println("i3.equals(i4): " + i3.equals(i4));

      

       System.out.println();

       System.out.println("i2 == i4: " + (i2 == i4));

       System.out.println("i2.equals(i4): " + i2.equals(i4));

      

       System.out.println();

       System.out.println("i == i2: " + (i == i2));

       System.out.println("i2.equals(i): " + i2.equals(i));

      

       System.out.println();

       System.out.println("i == i4: " + (i == i4));

       System.out.println("i4.equals(i): " + i4.equals(i));

      

    }

}

 

输出结果为:

   i1 == i2: true

   i1.equals(i2): true

 

   i3 == i4: false

   i3.equals(i4): true

 

   i2 == i4: false

   i2.equals(i4): true

 

   i == i2: true

   i2.equals(i): true

 

   i == i4: true

i4.equals(i): true

 

第一行和第二行说明,i1i2是引用了同一个对象,而且内容也相同。第三行和第四行说明i3i4引用了不同的对象,但是内容是相同的。第五行和第六行说明i2i4引用了不同的对象,但是内容是相同的。第七行和第八行说明经过i经过转型之后引用了i2引用的对象,而且内容相同。第九行和第十行,同样说明了经过i经过转型之后引用了i4引用的对象,而且内容相同。但是从第五行和第六行来看,i2i4是不同的对象,我的猜测是i在转型过程中引用了“==”右边引用的对象,看起来挺神奇的。

 

好了,关于equals和“==”的研究就暂时先告一段落吧~~不对的地方请多多指正啊。

 

posted @ 2012-04-20 11:16  Mr. Coding  阅读(346)  评论(0编辑  收藏  举报