String字符串的==、equals方法以及对象的==、equals方法的区别

来源:互联网 发布:天涯明月刀ol捏脸数据 编辑:程序博客网 时间:2024/05/16 11:52

前言:我们都知道String也是对象,但是用String的==和equals()来判断和其他对象的==和equals()来判断的结果是不是一样呢?看代码:

package zm.demo;import java.util.HashMap;import java.util.Iterator;import java.util.Map;public class Demo {    public static void main(String[] args) {        Person p1 = new Person(1, "张三", 20);        Person p2 = new Person(1, "张三", 20);        System.out.println("比较p1=p2  :" + (p1==p2));        System.out.println("比较p1.equels(p2) :" + (p1.equals(p2)));        String s1 = "C博客";        String s2 = "C博客";        System.out.println("比较s1=s2  :" + (s1==s2));        System.out.println("比较s1.equels(s2) :" + (s1.equals(s2)));    }}

看结果:

比较p1=p2  :false比较p1.equels(p2) :false比较s1=s2  :true比较s1.equels(s2) :true

明明都是对象,都是比较的==和equals,为什么结果却完全相反呢???
原因:
我们先来说equals()方法:
我们都知道所有的对象基类都是Object,因此我们看Object的源码:

  public boolean equals(Object obj) {    return (this == obj);    }

这就是Object#equals源码,所以,实际上Object的equals方法和==并没有任何区别,就是一样的,因此普通对象的==和equals()都是一样的,比较的是是否为同一对象
而String,它之所以不同,就是因为它重写了equals方法:
看String#equals源码:

public boolean equals(Object anObject) {    if (this == anObject) {        return true;    }    if (anObject instanceof String) {        String anotherString = (String)anObject;        int n = count;        if (n == anotherString.count) {        char v1[] = value;        char v2[] = anotherString.value;        int i = offset;        int j = anotherString.offset;        while (n-- != 0) {            if (v1[i++] != v2[j++])            return false;        }        return true;        }    }    return false;    }

所以,String的equals方法实际上比较的是它的值是否相同。

String的==比较,为什么这里String的==得出得结果也是true呢?
这就涉及到了String的常量池了,String s1 = “C博客”;JVM会首先去常量池中查找是否有”C博客”这个字符串常量,有的话就返回引用地址给s1,没有就将”C博客”字符串常量放入常量池,再返回地址给s1,s2也是”C博客”字符串常量,因此JVM会将常量池中的该字符串引用地址返回给s2,因此实际上s1和s2指向的是同一个字符串字面量,所以才会为true。

再来看这个:

String s3 = new String("C博客");String s4 = new String("C博客");System.out.println("比较s3=s4  :" + (s3==s4));System.out.println("比较s3.equels(s4) :" + (s3.equals(s4)));

得出的结果:

比较s3=s4  :false比较s3.equels(s4) :true

这又是为什么呢?实际上这也涉及到String的内存分布和常量池了:
上面代码在运行期间的内存分配:

  1. JVM首先会去常量池中查找有没有一个叫“C博客”的字符串常量,如果有,就获取它的引用地址,没有就在常量池(jdk1.7好像常量池也在堆内)中创建一个再返回引用地址;
  2. 然后遇到了new,就会在堆内存中分配一块内存存储一个叫new String()的对象,该对象里就含有常量池中那个字符串的引用地址;
  3. 在栈内存中创建一个叫s3的变量,指向堆内存中的刚刚创建的对象;
  4. 对s4分配内存的时候,也会先去常量池中查找,因为s3已经在常量池中创建了”C博客”的字符串常量,因此就只会返回该字符串的引用地址;
  5. 在堆中又分配一块内存给一个叫new String()的对象,该对象里也有指向常量池中”C博客”字符串常量的地址;
  6. 在栈内存中创建一个叫s4的变量,指向堆内存中的刚刚创建的对象。

所以,s3和s4的==比较的时候返回的是false,因为它们指向是不同的对象,而s3.equals(s4)返回true,就是因为String内重写了equals方法了,比较的是对象里的内容,它们都指向常量池中的同一个叫”C博客”的字符串,因此相等。

原创粉丝点击