面试题答案
一键面试- 性能差异:
- 使用 + 号:
- 在编译期,Java编译器会将多个字符串常量的“+”拼接优化为一个常量。例如
String s = "a" + "b";
,编译后等同于String s = "ab";
。 - 但如果有变量参与拼接,每次使用“+”号都会创建一个新的
String
对象。因为String
是不可变的,每次拼接都会生成新的字符串实例,性能较差。例如:
- 在编译期,Java编译器会将多个字符串常量的“+”拼接优化为一个常量。例如
- 使用 + 号:
String result = "";
for (int i = 0; i < 1000; i++) {
result = result + i;
}
- 这里每次循环都会创建新的`String`对象,随着循环次数增加,性能开销显著增大。
- 使用
StringBuilder
的append
方法:StringBuilder
是可变的字符序列,append
方法在原有的字符序列上进行操作,不会每次都创建新的对象。- 它是非线程安全的,在单线程环境下性能较高。例如:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
- 这种方式在循环拼接字符串时,性能远远优于使用“+”号,因为避免了大量中间`String`对象的创建。
- 使用
StringBuffer
的append
方法:StringBuffer
同样是可变的字符序列,append
方法也是在原有的字符序列上操作。- 它是线程安全的,因为其方法都被
synchronized
关键字修饰。但在多线程环境下,同步操作会带来一定的性能开销。例如:
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
- 在单线程环境下,其性能略低于`StringBuilder`,因为多了同步的开销。
2. 场景选择:
- 单线程环境:
- 如果只是简单的少量字符串拼接,使用“+”号可读性较好,性能也不会有太大问题。例如
String s = "Hello" + " " + "World";
- 但如果是在循环中进行大量字符串拼接,优先选择
StringBuilder
,因为其性能优势明显,能避免创建大量中间对象,提高程序执行效率。
- 如果只是简单的少量字符串拼接,使用“+”号可读性较好,性能也不会有太大问题。例如
- 多线程环境:
- 必须使用
StringBuffer
,因为它的线程安全性可以保证在多线程并发操作时,字符串拼接的正确性。虽然性能比StringBuilder
略低,但能确保数据一致性。例如在多线程的日志记录模块中,多个线程可能同时进行字符串拼接操作,此时使用StringBuffer
能避免数据竞争问题。
- 必须使用