String、StringBuffer和StringBuilder源码解析
1.String
1.1类的定义
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
String类在定义时候使用final关键字进行修饰,限制了这个类无法被继承,里面的方法也无法被重写。
同时它还实现了Serializable接口、Comparable接口,以及CharSequence接口三个接口:
- Serializable:序列化接口,如果允许对象被序列化需要实现该类。
- Comparable:比较对象大小的接口,用来定义对象之间如何进行大小的比较。
- CharSequence:字符序列接口,相比String类,它是一个更为广泛的可读可写字符序列,而String类是只可读的。
1.2类的成员变
/** The value is used for character storage. */
private final char value[]; /** Cache the hash code for the string */
private int hash; // Default to 0
String类中常用的两个成员变量value、hash。
- value:字符类型的数组,用来存放我们所保存的字符串,每一个字符串都会被拆开作为字符来进行存储。
- hash:对应字符串的hash值。
1.3常用方法
length():返回value数组的长度。
public int length() {
return value.length;
}
indexOf(str):获取在字符串中某个字符串的起始位置。这里其实也是用的遍历,从指定的开始位置起,一直遍历直到找到目标字符串,或者直到源字符串的最后一位(其实是最后一位减去目标字符串的长度)。
public int indexOf(String str) {
return indexOf(str, );
} public int indexOf(String str, int fromIndex) {
return indexOf(value, , value.length,
str.value, , str.value.length, fromIndex);
} static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == ? sourceCount : -);
}
if (fromIndex < ) {
fromIndex = ;
}
if (targetCount == ) {
return fromIndex;
} char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
} /* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + ;
int end = j + targetCount - ;
for (int k = targetOffset + ; j < end && source[j]
== target[k]; j++, k++); if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -;
}
compareTo(str):比较两个字符串的大小,采用的是逐个字符来进行比较(比较ASCII码)。
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value; int k = ;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
1.4总结
String类是一个可序列化,可按照字符大小进行排序,不可继承、只读的字符序列类。
2.StringBuilder
2.1类定义
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
StringBuilder和String的定义类似,同样被final关键字修饰,限定了无法被继承,同时继承Serializable和CharSequence两个接口。
同时最它多继承了一个抽象类AblstractStringBuilder。
2.2成员变量
在StringBuilder中没有再定义其他的成员变量,所使用的底层存放数据的变量来自于父类AbstractStringBuilder。
在AbstractStringBuilder中,定义了三个成员变量
char[] value; int count; private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - ;
- value:字符数组,用来存放传入的字符串。
- count:int类型,记录value中存放元素的长度。
- MAX_ARRAY_SIZE:静态常量,代指允许value数组的最大长度。
2.3常用方法
append(str):相比String只读的属性,StringBuilder允许我们对其进行写操作。但是由于底层存放数据的是一个数组,因此每次都需要进行一个扩容的判断。如果count+入参字符串的长度大于当前数组value的长度,就需要进行扩容,每次扩容后的数组长度=原长度*2+2。
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(, len, value, count);
count += len;
return this;
} private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > ) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
} private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << ) + ;
if (newCapacity - minCapacity < ) {
newCapacity = minCapacity;
}
return (newCapacity <= || MAX_ARRAY_SIZE - newCapacity < )
? hugeCapacity(minCapacity)
: newCapacity;
}
2.4总结
StringBuilder补充了String只能读不能写的属性,采用对数组扩容的操作,允许程序员对String类型来进行写操作。
3.StringBuffer
3.1类定义
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
StringBuffer的定义与StringBuilder类似,同样继承了AbstractStringBuilder抽象类,实现了Serializable和CharSequence接口。
3.2成员变量
StringBuffer的成员变量和StringBuilder一样,同样适用在AbstractStringBuilder中定义好的字符类型数组value和int类型count。
3.3常用方法
append(str):与StringBuilder类似的,两个类都是通过调用AbstractStringBuilder中的append(str)方法来添加字符串。
区别在于StringBuffer的方法定义上多了一个关键字:Synchronized。通过这个关键字,来保证我们对字符串的写操作的线程安全。
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
toString():和StringBuilder的toString()方法不一样,这里在StringBuffer中就已经完成了对字符数组的复制,如果连续调用toString()方法,实际返回的都是同一个String对象。而在StringBuilder中,由于数组的复制是发生在String类里面,因此每次调用后返回的都是不同的String对象。
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, , count);
}
return new String(toStringCache, true);
}
3.4总结
StringBuffer在Stringbuilder实现了字符串写操作的基础上,又添加了对它的线程安全方面的维护,通过查看源码,可见都是通过在方法上添加synchronized关键字来显示的。这样虽然可以保证线程安全,但是也在一定程度上,舍弃了部分性能。不过在jdk1.5之后对锁的优化,新增了偏向锁、轻量级锁后,如果我们对字符串的写操作不涉及多线程的时候,StringBuffer和StringBuilder的资源损耗是几乎类似的。但如果一旦涉及多线程,StringBuffer则能更好的保障我们的线程安全。
4.总结
String类是java中定义用来保存一个字符序列的对象,但是对它的操作只有读,而没有写。所有的写操作实际都是返回了一个新的字符串对象。
StringBuilder类在String类的基础上,增加了对字符序列的写操作,采用底层数组扩容的方式,来允许添加新的字符串,或删除里面原有的字符串。
StringBuffer类由在StringBuilder类的基础上,既满足了对字符序列的写操作,又保证了操作的线程安全。因此在实际情况下,优先推荐使用StringBuffer类。
成员变量
String类型
String、StringBuffer和StringBuilder源码解析的更多相关文章
- String,StringBuffer和StringBuilder源码解析[基于JDK6]
最近指导几位新人,学习了一下String,StringBuffer和StringBuilder类,从反馈的结果来看,总体感觉学习的深度不够,没有读出东西.其实,JDK的源码是越读越有味的.下面总结一下 ...
- [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析
String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识, ...
- String、StringBuffer、StringBuilder源码分析
利用反编译具体看看"+"的过程 1 public class Test 2 { 3 public static void main(String[] args) 4 { 5 int ...
- Stringbuffer与Stringbuilder源码学习和对比
>>String/StringBuffer/StringBuilder的异同 (1)相同点观察源码会发现,三个类都是被final修饰的,是不可被继承的.(2)不同点String的对象是不可 ...
- String、StringBuffer、StringBuilder源码解读
序 好长时间没有认真写博客了,过去的一年挺忙的.负责过数据库.线上运维环境.写代码.Code review等等东西挺多. 学习了不少多方面的东西,不过还是需要回归实际.加强内功,方能扛鼎. 去年学习M ...
- StringBuffer 和Stringbuilder源码分析
首先看一下他们的继承关系 这个两个对象都继承了AbstractStringBuilder抽象类. 1.他们的实现方式都一样的,唯一区别的StringBuffer在多线程的时候是保证了数据安全, ...
- String的equals()方法源码解析
每个String对象在创建的时候都构造了一个char类型的final声明的不可替换数组,数组中的每一个元素即字符串对应的每一个字符如图: String的equals()在比较的时候会进行两步比较: 1 ...
- String,StringBuffer和StringBuilder的异同
String,StringBuffer和StringBuilder的异同 ...
- 小学徒成长系列—StringBuilder & StringBuffer关键源码解析
在前面的博文<小学徒成长系列—String关键源码解析>和<小学徒进阶系列—JVM对String的处理>中,我们讲到了关于String的常用方法以及JVM对字符串常量Strin ...
随机推荐
- day 83 Vue学习四之过滤器、钩子函数、路由、全家桶等
Vue学习四之过滤器.钩子函数.路由.全家桶等 本节目录 一 vue过滤器 二 生命周期的钩子函数 三 vue的全家桶 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 Vue的过滤 ...
- centos7 将home目录空间扩容到根目录
[root@localhost ~]# umount /home/ [root@localhost ~]# lvremove /dev/mapper/centos-home Do you really ...
- 现代软件工程HW1:词频统计
作业详细要求:http://www.cnblogs.com/denghp83/p/8627840.html 基本功能 1. 统计文件的字符数(只需要统计Ascii码,汉字不用考虑,换行符不用考虑,'\ ...
- Android开发 输入法调用学习
方法一(如果输入法在窗口上已经显示,则隐藏,反之则显示) InputMethodManager imm = (InputMethodManager) getSystemService(Context. ...
- [转]成为Java顶尖程序员 ,看这11本书就够了
“学习的最好途径就是看书“,这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 1.能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一本好书的价值远超 ...
- leetcode146周赛-1131-绝对值表达式的最大值
题目描述: class Solution: def maxAbsValExpr(self, arr1, arr2) -> int: def function(s1,s2): result1=[] ...
- 2016.8.19上午初中部NOIP普及组比赛总结
2016.8.19上午初中部NOIP普及组比赛总结 链接:https://jzoj.net/junior/#contest/home/1338 这次总结发得有点晚啊!我在这里解释一下, 因为浏览器的问 ...
- Python3基础笔记_字典
# Python3 字典 dict = {'} # 1.访问字典里的值 ,字典中没有key会报错 # 2.修改字典 print("修改之前:", dict['Beth']) dic ...
- 「BZOJ2391」Cirno的忧郁
传送门 设p[0] = (-10001,-10001) 把所有点按p[0]极角排序, s[i][j]表示三角形p[0]p[i]p[j]内的总价值,若i到j极角增大则s为正,否则s为负. 那么答案就是按 ...
- Centos--swoole平滑重启服务
平滑重启: 已经打开的服务: 首先在server服务中为进程添加名字: /** * @param $server */ public function onStart($server) { swool ...