JAVA中==与equals的区别

  equals如果没有被重写的话,和==的作用是一样的,都是判断两个对象引用是否指向同一个地址。一般重写了equals()方法就表示比较它们“实际意义上相等”,比较的是内容,而不是引用地址。Java中String重写了equals方法,所以此时比较的是两者的内容是否相等,而==比较的永远是地址。

package testPage;

/*
 * ==和equals有何区别
 * 这是在网上偶然看到的一个帖子,如果让我说,还真说不清楚,所以决定一探究竟。
 * 
 */

public class StringAndEquals {

    public static void main(String[] args) {
        // 案例1
        String a = "abc";
        String b = "abc";
        System.out.println("a==b的结果是:" + (a == b)); // 结果:true
        System.out.println("a.equals(b)的结果是" + (a.equals(b))); // 结果:true

        // 案例2
        String c = new String("abc");
        String d = new String("abc");
        System.out.println("c==d的结果是:" + (c == d)); // 结果:false
        System.out.println("c.equals(d)的结果是" + (c.equals(d))); // 结果:true

        // 案例3
        String s1 = "Monday";
        String s2 = new String("Monday");
        if (s1 == s2) {
            System.out.println("s1 == s2");
        } else {
            System.out.println("s1 != s2"); // 输出这句话
        }
        if (s1.equals(s2)) {
            System.out.println("s1 equals s2"); // 输出这句话
        } else {
            System.out.println("s1 not equals s2");
        }

        // 案例4
        String s3 = "Monday";
        String s4 = new String("Monday");
        s4 = s4.intern();
        if (s3 == s4) {
            System.out.println("s3 == s4"); // 输出这句话
        } else {
            System.out.println("s3 != s4");
        }
        if (s1.equals(s4)) {
            System.out.println("s3 equals s4"); // 输出这句话
        } else {
            System.out.println("s3 not equals s4");
        }

    }

}

  对于案例1,在内存堆中还有个东西就“串池”,当你以赋值的形式,即String a = "abc";给a赋值,系统会先在“串池”里找有没有,没有就创建,如果有,就直接给赋值了。在这里例子中String a = "abc",之前“串池”中没有,于是系统创建了一个,String b = "abc"到“串池”中寻找的时候,有了,于是直接赋与内存地址,因此输出为true。

  对于案例2,直接new出来的字符串不在“串池”中,因此每次new的是不“==”的。

  对于案例3,结合前两个案例的解析,很容易开出原因。

  对于案例4,加入了inter()方法,intern()后字符串可以直接 == 进行比较,速度提高了3倍。java.lang.String的intern()方法"abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方法没什么用处。但实际上,它做了个小动作:检查字符串池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会 把"abc"添加到字符串池中,然后再返回它的引用。

  我们清楚了用法之后,看一下原理吧,首先是equals的源码:

public boolean equals(Object anObject) { 
  if (this == anObject) { 
    return true; 
  } 
}

  如果重写了equals方法,比如String类中的equals方法,源码如下:

 /**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
     *
     * @param  anObject
     *         The object to compare this {@code String} against
     *
     * @return  {@code true} if the given object represents a {@code String}
     *          equivalent to this string, {@code false} otherwise
     *
     * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count; // 这里的count是事先定义的一个属性,初始值为字符串的size
        if (n == anotherString.count) {
          char v1[] = value; // value为字符串转化的字符数组
          char v2[] = anotherString.value;
          int i = offset; // offset默认为0
          int j = anotherString.offset;
          while (n-- != 0) {
              if (v1[i++] != v2[j++])
                return false;
          }
          return true;
        }
    }
    return false;
    }

  从上面的代码,我们可以这样其实在地址不相等的情况下会继续比较值,如果值相等,返回true。而==返回的结果和重不重写equals没关系,重写equals只会对Object.equals(Object)的结果造成影响。

  所以,总的来说,我们可以得到下面的结论:

  java中的数据类型,可分为两类: 
    1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。 

    2.复合数据类型(类) 
      当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。

 

参考资料:

http://bbs.csdn.net/topics/300179403

http://www.cnblogs.com/zhxhdean/archive/2011/03/25/1995431.html

http://geyubin.iteye.com/blog/1145464

 

posted @ 2014-03-09 14:33  NW_KNIFE  阅读(970)  评论(0编辑  收藏  举报