zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    JS中原型对象中的constructor的作用?
    ES Module,commonjs和Typescript模块系统
    webpack中的hash、chunkhash和contenthash
    react-spring介绍(翻译)
    Typescript中的对象多可能类型推导的解决办法
    博客定制样式和脚本代码
    React和Vue对比
    CSS动画属性/重绘重排组合层/GPU加速 渲染优化相关及联系
    Object.create()探索
    await的错误处理问题,一个issue引发的ts社区的讨论
  • 原文地址:https://www.cnblogs.com/ningvsban/p/3589991.html
Copyright © 2011-2022 走看看