面试题答案
一键面试String
- 底层实现:
String
类在Java中是不可变的,其底层使用char
数组存储字符串内容,并且final
修饰,一旦创建不可改变。例如:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; // 其他代码 }
- 线程安全性:
- 由于其不可变性,
String
是线程安全的。多个线程同时访问同一个String
对象时,不会出现数据竞争问题,因为String
对象的状态不会改变。
- 由于其不可变性,
- 性能:
- 当对
String
进行频繁修改操作时(如拼接等),性能较差。因为每次修改都会创建新的String
对象,例如String s = "a" + "b" + "c";
,实际上会创建多个中间的String
对象,消耗额外的内存和时间。
- 当对
StringBuffer
- 底层实现:
StringBuffer
类继承自AbstractStringBuilder
,底层也是通过char
数组存储字符串,但是这个数组是可变的。例如:
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence { // 继承AbstractStringBuilder的char数组,如: // char[] value; 在AbstractStringBuilder中定义 // 其他代码 }
- 它的方法很多都使用
synchronized
关键字修饰,以保证线程安全。例如append
方法:
@Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
- 线程安全性:
StringBuffer
是线程安全的。因为其关键方法(如append
、insert
等)都被synchronized
修饰,同一时间只有一个线程能访问这些方法,避免了数据竞争。
- 性能:
- 由于使用
synchronized
关键字,在多线程环境下,当一个线程访问StringBuffer
的同步方法时,其他线程需要等待,这会导致性能开销。在单线程环境下,相比StringBuilder
也会有性能损失,因为不必要的同步操作。
- 由于使用
StringBuilder
- 底层实现:
StringBuilder
同样继承自AbstractStringBuilder
,底层也是可变的char
数组。例如:
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence { // 继承AbstractStringBuilder的char数组,如: // char[] value; 在AbstractStringBuilder中定义 // 其他代码 }
- 它的方法没有使用
synchronized
修饰。例如append
方法:
@Override public StringBuilder append(String str) { super.append(str); return this; }
- 线程安全性:
StringBuilder
是非线程安全的。因为没有同步机制,多个线程同时访问和修改StringBuilder
对象时,可能会出现数据竞争问题,导致结果不可预测。
- 性能:
- 在单线程环境或者多线程但不需要同步的情况下,
StringBuilder
性能优于StringBuffer
,因为它没有同步带来的开销。在多线程环境下如果需要同步,就需要额外的同步机制来保证线程安全。
- 在单线程环境或者多线程但不需要同步的情况下,