1. String、StringBuffer和StringBuilder区别
答:String是不可变的,而StringBuffer和StringBuilder是可变的。
这样回答肯定是不满意的,面试官希望听到的是你能说出个为什么?而不是给我一个结论,只说结论面试官会认为你只是背了面试题而已。
2. 为什么String是不可变的?
简单的讲String是内部结构如下
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; ... }
是用final char value[]来存储字符串, 所以上不可变的。这么说肯定凉了。
final说明: 修饰的类不能被继承、修饰的方法不能被重写、修饰的基本数据类型变量是其值不能改变、修饰的引用类型变量是不能再指向其他对象。
所以final修饰的char value[],其组据是可变的。
为什么是不可变呢? 先看String的Api,提供了哪些public方法
从源码中可以看出
- String 并没有提供一个可以修改数组值的方法
- String是final类,不能被继承,也不可能有子类来修改
3.为什么StringBuffer和StringBuilder是可变的?
StringBugger和StringBuilder都继承自AbstractStringBuilder, StringBugger和StringBuilder存放字符串都放在AbstractStringBuilder的char[] value中。 而AbstractStringBuilder提供如append来修改value的值。所以是可变的。
4. StringBuffer和StringBuilder的区别?
1. 先看看源码,如下
StringBuffer的公开方法加了对象锁,所以是线程安全的,而StringBuilder没有,所以是线程不安全
2. StringBuffer的API加了对象锁,执行速度慢(效率慢)。StringBuilder未加锁,执行速度快(效率高)。
3. toString方法不同,直接看源码:
注: toStringCache的定义是 private transient char[] toStringCache
从源码看出:
- StringBuffer的toString都会直接使用缓存区的toStringCache值来构造一个字符串
- 而StringBuilder是需要复制一次字符数组,再构造一个字符串
5. StringBuffer和StringBuilder相同之处?
- 字符串都可变
- 默认初始容量都是16
- 扩容机制相同。源码如下:
都是调父类AbstractStringBuilder 的扩容方法,源码如下: private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } } private int newCapacity(int minCapacity) { // overflow-conscious code int newCapacity = (value.length << 1) + 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity; } private int hugeCapacity(int minCapacity) { if (Integer.MAX_VALUE - minCapacity < 0) { // overflow throw new OutOfMemoryError(); } return (minCapacity > MAX_ARRAY_SIZE) ? minCapacity : MAX_ARRAY_SIZE; }