首先我们要知道:
1、String是final类,是字符串常量。意味着一个String对象不可继承,不可改变,所以如下代码:
String str = "abc";
str += "d";
其实是重新创建一个String对象,执行代码后,改变引用。所以每当我们对String对象进行操作时,都是在重复创建大量新String对象,原来对象等待被GC收集,效率大大降低,所以要避免使用"+="来构造字符串。
值得一提的是这样的代码:
(1)String temp = "You are" + "a" + "SB!";
(2)StringBuffer result = new String().append("You are").append("a").append("SB!");
(1)的效率要好于(2)。这是因为(1)相当于:
String temp = "You are a SB!"
所以temp的创建速度是很快的,而(2)编译StringBuffer后还要进行append处理,开销比较大。但是如果是这样:
String temp1 = "You are";
String temp2 = "a";
String temp3 = "SB!";
String result = temp1+temp2+temp3;
此时,JVM会按照原来的规则执行。所以我们要记住,不要简单的认为.append效率要好于"+"。
扩展知识:
- String的创建
String s = "Hello";
JVM先根据内容"Hello"查找对象,如果没有,则在heap上创建新对象并赋值s,否则使用已经存在的对象。
String s = new String("Hello");
JVM直接在heap上创建新对象,所以在heap上会出现内容相同而地址不同的两个String对象,这给我们的启发是不要用new创建String
知道了这两条以后,我们来看这道题:
//以下程序创建了几个对象?
String A,B,C
A = "a";
B = "b";
A = A + B;
StringBuffer D = new StringBuffer("abc");
D = D.append("567");
前三行肯定是3个了,第四行根据我们上面的知识点,是2个,最后一行,是对象自身改变,没有新对象,所以一共是5个。
- String的比较
"=="是比较地址,"equls"是比较内容。
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
s1 == s2; //true 地址相同
s1 == s3; //false 地址不同
s1.equals(s2);//true 内容相同
s1.equals(s3);//true 内容相同
StringBuilder > StringBuffer > String
扩展知识:
//下面两段程序哪个效率更好
StringBuffer s = new StringBuffer ();
for(int i =0; i<50000; i++){
s.append("hello");
}
StringBuffer s = new StringBuffer (250000);
for(int i =0; i<50000; i++){
s.append("hello");
}
答案是第二个。
因为StringBuffer内部实现的是char数组,默认初始长度为16,每当字符串长度大于数组长度时,JVM会构造更大的新数组,然后将原先的数组内容复制到新数组,增加了开销,这给我们的启示是在声明StringBuffer对象时,指定合适的capacity,不要使用默认值。
3、StringBuilder是非线程安全的,StringBuffer是线程安全的,所以总结如下:
- 如果需要操作少量字符串,为了方便,我们用String;
- 处理单线程大量字符串,用StringBuilder;
- 处理多线程大量字符串,用StringBuffer;