title: 字符串连接原理
index_img: img/2.svg
tags:
- Java SE
- 字符串
categories:
- Java SE
hide: false
excerpt: 字符串拼接方式、效率、对象
使用+运算符
无变量参与
- 运行前就直接拼接为一个字符串
public class Main {
public static void main(String[] args) {
String s = "Hello " + "World"+"!";
}
}
在编译后实际上会变成:
public class Main {
public Main() {
}
public static void main(String[] var0) {
String var1 = "Hello World!";
}
}
jdk8之前(有变量参与)
public class Main {
public static void main(String[] args) {
String s1 = "Hello";
String s2 =s1+"world";
String s3 =s2+"!";
}
}
每次+堆中都会创建StringBuilder和String对象,字符串常量池中会添加Hello、World、!,效率低且浪费空间。(StringBuilder高效率是针对一个StringBuilder而言)
//等效代码
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
String s1 = "Hello";
sb.append(s1);
String s2 = sb.append("world").toString();
String s3 = sb.append("!").toString();
}
}
jdk8之后(有变量参与)
public class Main {
public static void main(String[] args) {
String s1 = "a";
String s2 = "b";
String s3 = "c";
String s4 = s1 + s2 + s3;
}
}
-
jdk8之前堆中会产生4个对象,字符串常量池中会有3个对象
-
jdk8之后堆中会产生1个对象,字符串常量池中会有3个对象
jdk8之后,每+都会产生新的预估数组和一个String对象,依旧效率低。
注意
先判断是否有变量参与,再判断是否分析常量池(会复用)和堆。
StringBuilder
StringBuilder 和 StringBuffer 是专门用于处理字符串连接的类。StringBuffer 是线程安全的,而 StringBuilder 不是,因此在不涉及多线程的情况下,一般推荐使用 StringBuilder
public class Main {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("a");
stringBuilder.append("b");
stringBuilder.append("c");
System.out.println(stringBuilder); // 还是StringBuilder对象
}
}
StringBuilder是可变的。只会产生一个。
StringBuilder (或 StringBuffer) 内部使用一个 char[] 数组来存储字符串。当数组容量不足以容纳新的字符时(StringBuilder默认16字节),它会创建一个新的数组,大小是旧数组的2倍+2,然后将旧数组的内容复制到新数组中。