String中的equals()方法和==解析

首先,String有两种使用方式,即作为对象来使用和基本类型来使用。

String s1 = new String(“Hello”); //作对象时,不会验证是否有相同字符串(即“Hello”),都会在堆中开辟空间存放new出来的对象,在栈中开辟一空间存放对象在堆中的地址,指向此对象。

String s2=”hi”;//作基本类型,声明时,会现在String Pool里查找有没有这个字符串,如果有直接引用指向,如果没有,则在String Pool创建一个。(之前常量池在PermGen里,java7之后放在heap(堆)中了)。

接下来说==和equals,==的意思就是都是比较是否指向堆同一个对象,这个不会变。

在Object里equals 是这样的

public boolean equals(Object obj) {

return (this == obj);

}

没错,是一样的,都是比较是否指向堆同一个对象。String类将equals方法重写

public boolean equals(Object anObject) {

if (this == anObject) {

return true;

}

if (anObject instanceof String) {

String anotherString = (String) anObject;

int n = value.length;

if (n == anotherString.value.length) {

char v1[] = value;

char v2[] = anotherString.value;

int i = 0;

while (n-- != 0) {

if (v1[i] != v2[i])

return false;

i++;

}

return true;

}

}

return false;

}

即比较字符串的内容的相同与否,(其实在JavaBean里很多都会重写equals(),用来比较对象里各个值的相同与否)。

这样解释后,那么还有一个疑点,基本类型和对象之间该怎么比较

String s1 = "Hello";

String s2 = new String("Hello");

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

S1指向的是StringPool里的对象,S2指向的是堆里的对象,两者并非同一个对象,但字符串相同。于是,

false

True

接下来再上几个案例便于理解。

1、

String s1 = new String("Hello");

String s2 = new String("Hello");

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

以上代码段的打印结果是:

false

true

没有指向同一个对象,并且字符串内容相同。

2、

String s1 = new String("Hello");

String s2 = s1;

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

以上代码段的打印结果是:

true

true

指向同一个对象,并且字符串内容相同。

3、

String s1 = "Hello";

String s2 = "Hello";

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

以上代码段的打印结果是:

true

true

指向同一个对象,并且字符串内容相同。

5、

String s1 = new String("Hello");
s2 = s.intern();

System.out.println(s1 == s2);
System.out.println(s1.equals(s2));

以上代码段的打印结果是:

true

true

intern()方法,工作中不常用,平常看博客偶尔会碰到,今天看了一下源码

 /**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class <code>String</code>.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this <code>String</code> object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this <code>String</code> object is added to the
     * pool and a reference to this <code>String</code> object is returned.
     * <p>
     * It follows that for any two strings <code>s</code> and <code>t</code>,
     * <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code>
     * if and only if <code>s.equals(t)</code> is <code>true</code>.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
    public native String intern();

intern()是个native(本地)方法,简而言之就是Java中声明的可调用的使用C/C++实现的方法。Java不提供函数体,但是我们可以看注释。当intern()被调用时,会先在常量池查找有没有这个字符串对象,有就返回,没有就加进去这个字符串对象。返回的也是常量池里的字符串对象。由此可见,s1与s2皆为来自常量池的同一个字符串对象。故==与equals返回的都是true。

猜你喜欢

转载自blog.csdn.net/qq_27474277/article/details/74451928