从源码看String,StringBuffer,StringBuilder的区别
前言
看了一篇文章,大概是讲面试中的java基础的,有如题这么个面试题。我又翻了一些文章看了下,然后去看源码。看一下源码大概能更加了解一些。
String
String类是final的,表示不可被继承,不可变的。注释上也有说明:
其中用一个char[]来保存String的值。
private final char value[];
一旦赋值,就不可改变。看一下,操作string的源码,例如 substring,replace,concat 等方法,最终结果都是返回 new String(...). 也就是重新创建了一个String对象。
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */ while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}
StringBuffer 和 StringBuilder
它两个都是继承自 AbstractStringBuilder 抽象类,不同的是StringBuffer类都是带有 synchronized 关键字的。也就是说,StringBuffer是线程安全的,而 StringBuilder不是。他们中的方法基本上调用 super的方法。也就是AbstractStringBuilder 里实现的方法。
平时用的比较多的就是 append 方法。我们看一下代码实现:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// 当append之后的长度大于当前value的长度的时候,需要重新生成一个char[]数组。
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
public static char[] copyOf(char[] original, int newLength) {
//重新创建一个char[]数组
char[] copy = new char[newLength];
//将之前的值赋值到该数组中
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
ensureCapacityInternal 方法中,将 value的值重新扩展比如 str.append("abc")。假如之前value的值为:{'h','e','l','l','o'},当调用 str.getChars方法之后,会将 abc 追加到value数组后,value值就变成 :{'h','e','l','l','o','a','b','c'}
其实 getChars 方法只是做了一件事情 :System.arraycopy。
如图:
执行完arraycopy之后
总结
String 不可变,StringBuffer和StringBuilder可变,但是StringBuilder非线程安全。可以根据他们不同的特性分情况使用。
最新文章
- Python 进程间通信
- 如何下载youtube上面的视频
- 第七节:Class与Style绑定
- display:inline-block 去除间隙
- JQuery.getJSON 从aspx页面返回JSON数据
- js判断IE浏览器版本
- oracle中between
- .NET Framework 4.5、4.5.1 和 4.5.2 中的新增功能
- 如何用C#代码查找某个路径下是否包含某个文件
- bzoj3555: [Ctsc2014]企鹅QQ
- Android(java)学习笔记203:网页源码查看器(Handler消息机制)
- 尚学堂Java面试题整理
- Visual Studio 2012的开发使用技巧
- APP品牌具体有哪几个要素?又是如何操作的?
- 『开源』扩展 JS 的 Date 处理函数
- python下调用pytesseract识别某网站验证码
- MSSQL 转 ACCESS 在表格结构上应注意的
- NIO框架之MINA源码解析(五):NIO超级陷阱和使用同步IO与MINA通信
- 关于text-align和text-align-last
- Deque 双端队列 Stack 堆栈
热门文章
- Spring学习笔记:Spring动态组装打印机
- python __new__()分析
- Csharp: speech to text, text to speech in win
- 23_ConcurrentLinkedQueue
- 如何实现Docker应用的自定义弹性伸缩
- Raspberry Config.txt 介绍
- Android网络通信库Volley简介(转)
- 4 关于word2vec的skip-gram模型使用负例采样nce_loss损失函数的源码剖析
- 记重回IT行业的面试
- Day02——Python基本数据类型