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 ...
随机推荐
- 快速搭建Bootstrap
粘贴下面代码,快速开启Bootstrap的搭建: <!DOCTYPE html> <html lang="en"> <head> <met ...
- 论文阅读-(CVPR 2017) Kernel Pooling for Convolutional Neural Networks
在这篇论文中,作者提出了一种更加通用的池化框架,以核函数的形式捕捉特征之间的高阶信息.同时也证明了使用无参数化的紧致清晰特征映射,以指定阶形式逼近核函数,例如高斯核函数.本文提出的核函数池化可以和CN ...
- JS流程控制语句 反反复复(while循环) 和for循环有相同功能的还有while循环, while循环重复执行一段代码,直到某个条件不再满足。
反反复复(while循环) 和for循环有相同功能的还有while循环, while循环重复执行一段代码,直到某个条件不再满足. while语句结构: while(判断条件) { 循环语句 } 使用w ...
- Dash Speed【好题,分治,并查集按秩合并】
Dash Speed Online Judge:NOIP2016十联测,Claris#2 T3 Label:好题,分治,并查集按秩合并,LCA 题目描述 比特山是比特镇的飙车圣地.在比特山上一共有 n ...
- Qt : 隐式数据共享(copy on write)
copy on write 意思当内容有变动的时候,才对容器中的数据结构进行复制.否则仅作共享. QT许多类中使用了隐式数据共享技术,来最大化资源利用率和最小化拷贝时的资源消耗. 在数据传递时,其实只 ...
- 五. Arrow Function 箭头函数
箭头函数三大好处: 1. 简明的语法 举例: 如果只有一个参数,可以不加(),多个参数用 "," 隔开 2. 隐式返回 首先说下什么是显示返回,显示返回就是 return 加上你要 ...
- day3-编码、文件、集合、函数、递归
学习内容: 1. 文件编码 2. 文件 3. 集合 4.函数 5.递归 6.匿名函数 1. 文件编码: 常见的字符串编码有:ASCII 扩展的ASCII Unicode GBK GB2312 GB18 ...
- ActiveMQ 知识点
消息队列高可用 持久化,事务,签收,zookeeper+replicated-leveldb-store的主从集群 异步发送 同步发送: 明确指定同步发送 未使用事务的前提下,发送持久化消息(会使用同 ...
- hdu6088 组合数+反演+拆系数fft
题意:两个人van石头剪子布的游戏一共n盘,假设A赢了a盘,B赢了b盘,那么得分是gcd(a,b),求得分的期望*\(3^{2*n}\) 题解:根据题意很明显有\(ans=3^{n}*\sum_{a= ...
- Ubuntu 快速安装配置Odoo 12
Odoo 12预计将于今年10月正式发布,这是一次大版本更新,带来了一些不错的新特性,如 文件管理系统(DMS) 用户表单中新增字段(Internal user, Portal, Public) HR ...