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,然后将旧数组的内容复制到新数组中。