JDK-StringBuilder

先说String

String类被final修饰, 不可以被继承. 内部用char数组来保存字符串, 并且类变量多数也是final的, 一些操作方法比如:substring(), concat()等方法都是构造一个新的char数组, new一个String对象来实现的. 字符串用”+”连接相当于新建了一个String对象.(编译器识别到字符串相加操作会优化成StringBuilder, 同时若编译期间就能确定字符串相加的值或final域, 那么会直接被优化为结果).

不可变类可是使用池技术来优化相同内容的对象占用的内存空间. 结合intern()方法, 可以把new出来的String对象刷新入常量池.

问题: String str = new String(“abc”) 创建了多少个对象?

类加载? 代码执行?

StringBuilder

StringBuilder内部持有非final的char数组, 类似ArrayList有扩容机制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 在执行append前, 会确保容量
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;
}

null safe

1
2
3
4
5
6
7
8
9
10
11
12
// null值时执行下面代码
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}

StringBuffer

这个嘛, StringBuilder方法加同步.