概述
简要的介绍了JDK源码中,StringBuilder和StringBuffer类的几个常用细节点,以加深对其内部原理的认识。夯实读者Java基础知识。
分析
StringBuffer的中使用缓存机制
private transient char[] toStringCache;
此缓存,会在toString时获取数据,但是会在任何修改操作时清除缓存数据
StringBuffer基本情况
StringBuffer中默认初始容量为16,指定字符串初始化时获得容量为字符串的长度+16。也可以指定容量初始化。public StringBuffer() { super(16); } public StringBuffer(int capacity) { super(capacity); } public StringBuffer(String str) { super(str.length() + 16); append(str); }
StringBuffer的方法用synchronized修饰,因此其是线程安全的
@Override public synchronized void setLength(int newLength) { toStringCache = null; super.setLength(newLength); } /** * @throws IndexOutOfBoundsException {@inheritDoc} * @see #length() */ @Override public synchronized char charAt(int index) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index); return value[index]; } .......
生成字符串逻辑
@Override public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
其实,先是将数据写到缓存中,然后再从缓存中取数据,如果缓存已有数据,之间从缓存中获得,这样提高执行速度。
与StringBuilder和String比较
对于String来说,String str = “adc”, 在Java虚拟机中str为adc时是一个变量,当str被重新赋值为adcef时为另一个变量,
被重新分配了一次内存,上次使用的内存会被gc在适当的时候回收掉。由于这种机制导致了如果有大量的String赋值操作时,会导致运行速度的缓慢,
以及内存使用量的上升。对于StringBuilder来说,当我们在字符串缓冲区去被多个线程使用时,JVM不能保证StringBuilder的线程是安全的,
虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况是在单线程下进行的,
所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
总结
- 相比于StringBuilder和String来说,StringBuffer是线程安全的,因此多线程环境时优先考虑
- StringBuilder与StringBuffer的接口兼容,若在单线程环境下,使用StringBuilder,其无锁机制,因此执行速度快
- String是字符串常量,StringBuilder和StringBuffer是字符串变量,能够对字符串增删
- 执行速度上,StringBuilder最快,StringBuffer次之,String最慢