Let's Go!

java String的equals,intern方法 (转载)

上一篇 / 下一篇  2011-02-23 13:22:01 / 个人分类:JAVA学习&编程相关

java String的equals,intern方法

JAVA中的equals和==的区别

 

==比较的是2个对象的地址,而equals比较的是2个对象的内容。

显然,当equals为true时,==不一定为true;

 

基础知识的重要性,希望引起大家的重视,包括自己在内

很多困惑和疑问而且均来自于最基础的知识

折腾了一阵子又查了查书,终于对 String 这个特殊的对象有了点感悟

public class TestString {

    public static void main(String[] args) {

        String s1 = "Monday";

        String s2 = "Monday";

    }

}

有什么问题呢?

1. 来自 String 的忧虑

上面这段程序中,到底有几个对象呢?

可能很多人脱口而出:两个,s1 和 s2

为什么?

String 是 final 类,它的值不可变。

看起来似乎很有道理,那么来检测一下吧,稍微改动一下程序

就可以看到结果了:

public class TestString {

    public static void main(String[] args) {

        String s1 = "Monday";

        String s2 = "Monday";

        if (s1 == s2)

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

        else

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

    }

}

呵呵,很多人都会说已经不止两个对象了

编译并运行程序,输出:s1 == s2

啊!

为什么 s1 == s2 ?

== 分明是在说:s1 与 s2 引用同一个 String 对象 -- "Monday"!

2. 千变万化的 String

再稍微改动一下程序,会有更奇怪的发现:

public class TestString {

    public static void main(String[] args) {

        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");

    }

}

我们将 s2 用 new 操作符创建

程序输出:

s1 != s2

s1 equals s2

嗯,很明显嘛

s1 s2分别引用了两个"Monday"String对象

可是为什么两段程序不一样呢?

3. 在 String 的游泳池中游泳

哈哈,翻了翻书终于找到了答案:

原来,程序在运行的时候会创建一个字符串缓冲池

当使用 s2 = "Monday" 这样的表达是创建字符串的时候,程序首先会

在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被

放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1

将 s2 引用 s1 所引用的对象"Monday"

第二段程序中,使用了 new 操作符,他明白的告诉程序:

“我要一个新的!不要旧的!”与是一个新的"Monday"Sting对象被创

建在内存中。他们的值相同,但是位置不同,一个在池中游泳

一个在岸边休息。哎呀,真是资源浪费,明明是一样的非要分开做什么呢?

4. 继续潜水

再次更改程序:

public class TestString {

    public static void main(String[] args) {

        String s1 = "Monday";

        String s2 = new String("Monday");

        s2 = s2.intern();

        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");

    }

}

这次加入:s2 = s2.intern();

哇!程序输出:

s1 == s2

s1 equals s2

原来,程序新建了 s2 之后,又用intern()把他打翻在了池里

哈哈,这次 s2 和 s1 有引用了同样的对象了

我们成功的减少了内存的占用

5. == 与 equals() 的争斗

String 是个对象,要对比两个不同的String对象的值是否相同

明显的要用到 equals() 这个方法

可是如果程序里面有那么多的String对象,有那么多次的要用到 equals ,

哦,天哪,真慢啊

更好的办法:

把所有的String都intern()到缓冲池去吧

最好在用到new的时候就进行这个操作

String s2 = new String("Monday").intern();

嗯,大家都在水池里泡着了吗?哈哈

现在我可以无所顾忌的用 == 来比较 String 对象的值了

真是爽啊,又快又方便!

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ameyume/archive/2010/08/16/5815756.aspx

 

q956140151 发表于2010年12月4日 18:57:34  IP:114.250.111.*举报回复删除
请问在什么情况下会加入到常量池中呢?ameyume 发表于2010年12月4日 19:26:52  IP:211.102.166.*举报回复删除
回复 q956140151:那就在使用String s1 = "abc";时,会把abc加入到常量池中。还有一种情况是通过new创建的,但又执行了intern()函数后,会加入到常量池中,例如String s2 = new String("abc"); s2 = s2.intern();这时s2指向的就是常量池中的“abc”。我是这样理解的。
q956140151 发表于2010年12月4日 21:29:19  IP:114.250.111.*举报回复删除
回复 ameyume:String s = "ab"+"cd"; 会创建几个对象?分别在哪?对于new String("abc"); 在编译时不会将"abc"加到常量池中吗?
ameyume 发表于2010年12月4日 22:01:05  IP:211.102.166.*举报回复删除
回复 q956140151:如果要求没有在缓冲池中找到abcd,则在缓冲池中创建一个abcd字符串,即一个对象。 new的对象不会放在常量池中,new的是在堆中单独开辟内存。

ameyume 发表于2010年12月4日 22:03:10  IP:211.102.166.*举报回复删除
回复 ameyume:可参考 http://apps.hi.baidu.com/share/detail/10892143


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ameyume/archive/2010/08/16/5815756.aspx


TAG:

 

评分:0

我来说两句

Open Toolbar