一、String相关类层次
1. String
2. StringBuffer
3. StringBuilder
二、常用方法
1. 构造
String() :String的字符数组为final,所以不建议这么构造
String(byte[] bytes)
String(byte[], int offset, int length)
String(byte[], int offset, int length, String charsetName)
String(byte[], int offset, int length, Charset charset)
String(String original)
String(StringBuffer buffer)
String(StringBuilder builder)
2. 字符串链接
- 操作符+
- concat
- append
public class TestString {
public static void main(String[] args) {
String s1 = new String("hello ");
String s2 = new String("damon!");
System.out.println(s1 + s2);
System.out.println(s1.concat(s2));
StringBuilder sbuilder = new StringBuilder("hello ");
sbuilder.append("stefan!");
System.out.println(sbuilder);
StringBuffer sbuf = new StringBuffer("hello ");
sbuf.append("Elena!");
System.out.println(sbuf);
}
}
3. 子字符串:为啥StringBuilder没有这两个方法
public class TestString {
public static void main(String[] args) {
String s1 = new String("hello ");
System.out.println(s1.substring(1));
System.out.println(s1.substring(1,4));
}
}
4. 查找
public class TestString {
public static void main(String[] args) {
String s1 = new String("hello ");
System.out.println(s1.indexOf('l'));
System.out.println(s1.indexOf('l', 3));
System.out.println(s1.lastIndexOf('l'));
System.out.println(s1.lastIndexOf('l', 2));
}
}
5. 转换
public class TestString {
public static void main(String[] args) {
String s1 = String.valueOf(1);
String s2 = String.valueOf('a');
String s3 = String.valueOf(3.14);
int i = Integer.valueOf("3");
double d = Double.valueOf("3.14");
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(i);
System.out.println(d);
}
}
三、使用注意点及最佳实践
1. for循环中慎重用String +
public class TestString {
public static void main(String[] args) {
String s1 = new String("hello");
for (int i = 0; i < 10000; i++) {
s1 = s1 + i;
}
}
}
反编译
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String hello
6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
10: iconst_0
11: istore_2
12: iload_2
13: sipush 10000
16: if_icmpge 44
19: new #5 // class java/lang/StringBuilder
22: dup
23: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
26: aload_1
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: iload_2
31: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
34: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: astore_1
38: iinc 2, 1
41: goto 12
44: return
for循环中,会新建StringBuilder对象,调用append方法,每次循环都调用一次,性能差
2. String、StringBuffer、StringBuilder效率对比
public class TestString {
public static void main(String[] args) {
String s1 = new String("hello");
long t1 = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
s1 = s1 + i;
}
long t2 = System.currentTimeMillis();
System.out.println("String:" + (t2 - t1));
StringBuilder builder = new StringBuilder("hello");
long t3 = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
builder.append(i);
}
long t4 = System.currentTimeMillis();
System.out.println("StringBuilder:" + (t4 - t3));
StringBuffer buffer = new StringBuffer("hello");
long t5 = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
buffer.append(i);
}
long t6 = System.currentTimeMillis();
System.out.println("StringBuffer:" + (t6 - t5));
}
}
结果
String:331
StringBuilder:0
StringBuffer:1
- String在for循环中+会转化为创建StringBuilder对象的append方法,因为每次都创建对象,所以很慢
- StringBuilder相比于StringBuffer相比不需要同步,所以较快
四、其他注意点
1. 语法糖而非操作符重载
反编译后知道,String的+实际会被编译器转为StringBuilder.append()
参考
https://hollischuang.github.io/toBeTopJavaer/#/basics/java-basic/string-concat