nintenyun

导航

字符串驻留(String Interning)问题整理

//代码1
String sa=new String("Hello world");
String sb
=new String("Hello world");
System.
out.println(sa==sb); // false
//代码2
String sc="Hello world";
String sd
="Hello world";
System.
out.println(sc==sd); // true

    代码1中局部变量sa,sb中存储的是在堆中new出来的两个String对象的内存地址。虽然这两个String对象的值(char[]存放的字符序列)都是"Hello world"。 因此"=="比较的是两个不同的堆地址。代码2中局部变量sc,sd中存储的也是地址,但却都是常量池中"Hello world"指向的堆的唯一的那个拘留字符串对象的地址 。自然相等了。

//代码1
String sa = "ab";
String sb
= "cd";
String sab
=sa+sb;
String s
="abcd";
System.
out.println(sab==s); // false
//代码2
String sc="ab"+"cd";
String sd
="abcd";
System.
out.println(sc==sd); //true

代码1经历了机构步骤

创建stringbuild对象sab,同时用sa指向的拘留字符串对象完成初始化。然后调用append方法完成对sb所指向的拘留字符串的合并操作。

接着调用stringbuild sab对象的tostring()方法,最后将刚生成的String对象的堆地址存放在局部变量sab中。由于==操作符比较的是地址,sab和s的地址当然不一样 ,所以显示false。

代码2中"ab"+"cd"会直接在编译期就合并成常量"abcd", 因此相同字面值常量"abcd"所对应的是同一个拘留字符串对象,自然地址也就相同。

为什么STRING不可变?

字符串其实是由CHAR[] 数组组成, private const char[] value;  可能内部结构式这样的。

这个String对象中的value[]再也不能改变了。

为什么stringbuild 拼接效率优于 string?

public class Class1
{
public static void Main()
{
//代码1
string s = "hello";
string b = "world";
for (int i = 0; i < 100000; i++)
{
b
= b + s;
}
Console.WriteLine(b);
Console.Read();

//代码2
StringBuilder sb = new StringBuilder("hello");
StringBuilder sa
= new StringBuilder("world");
for (int i = 0; i < 100000; i++)
{
sb
= sb.Append(sa);
}
Console.WriteLine(sb);
Console.Read();
}

}

代码1效率比代码2低了很多

原因在于,b=b+s  这句语句,新建了一个stringbuild对象,调用append()方法,加入S,最后调用stringbuild的tostring()方法,新建一个新的string对象b,这样就会创建2次对象,由于要运行100000次,就要创造10万次string和stringbuild对象,这个开销不言而喻。

  

StringBuilder temp=new StringBuilder(a),
temp.append(b);
str
=temp.toString();

虽然在中间的时候也用到了append()方法,但是在开始和结束的时候分别创建了StringBuilder和String对象。

代码2 

只需要将自己的value[]数组不停的扩大来存放sa即可。循环过程中无需在堆中创建任何新的对象。效率高就不足为奇了。        

posted on 2011-02-12 14:41  nintenyun  阅读(247)  评论(0)    收藏  举报