如果面试的时候问:

“在字符串中equals和==的区别?”。

可以简单的这样回答:

“==比较的是字符串的内存地址;而equals比较的是字符串的内容”。

但分析的十分的浅,如果问的稍微深层点可能就卡壳了。平常就对java这两个东西比较一知半解的,今天好好地分析分析:

1、==

==在基本数据类型中比较的是值,而在引用类型中比较的是在内存中的存放地址。

2、equals

String类中的equals()方法是重写了object里的equals()方法,大致代码如下:

public boolean equals(Object anObject)
{
       //如果是同一个对象
        if (this == anObject)
        {
            return true;
        }
        //如果传递进来的参数是String类的实例
        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;
}

所以equals比较的是字符串内容。

但为什么有些时候String之间的比较可以用==呢?不是说==在字符串中比较的是内存地址吗?但由有些时候又不行,例如:

        String s1 = "ab";
        String s2 = "ab";
        System.out.println(s1==s2);
//        结果是true
        String d1 = "ab";
        String d2 = "a";
        String d3 = "b";
        String d4 =d2+d3;
        System.out.println(d1==d4);
//        结果是false

首先要对堆内存和栈内存有简单的了解:栈内存:存放基本类型的变量,对象的引用和方法调用;堆内存:存放所有new出来的对象和数组。(个人理解就是引用类型中就是一个放地址,一个放内容,而基本数据就放在栈内存中,这里写的有些含糊,最好自行百度)所以上面代码如下图所示:

s1==s2:
1.png

d1==d4:
2.png

第一个问题画的图其实是有点误区的,那个只是简单分辨。(String的存放地址不是栈,也不是我们创建对象时存放在的那个堆。而是独立的常量池)。但可以用引入“常量池”(字符串缓冲池)来解释:程序在运行的时候会创建一个字符串缓冲池当使用 s1 = "ab" 这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1,就将s2引用s1所引用的对象"ab"。

但为什么第二个不行呢?因为代码"String d4 =d2+d3;"事实上是是创建了一个StringBuilder对象,然后一直append。换句话说String d4 = d2 + d3;就是String d4 = new StringBuilder().append(d2).append(d3).toString()。
所以d4是一个new出来的对象,new出来的就要开辟新的地址。所以它指向的是新的堆内存,而d1其实是指向常量池上。所以两者不相等。

参考

本文参考了如下文章 :