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 ...
随机推荐
- day25-静态、组合、继承
#!/usr/bin/env python # -*- coding:utf-8 -*- # ----------------------------------------------------- ...
- Python flask 构建微电影视频网站✍✍✍
Python flask 构建微电影视频网站 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大 ...
- AWS云管理平台
- struts2文件上传,文件类型 allowedTypes对应
'.a' : 'application/octet-stream', 2 '.ai' : 'application/postscript', 3 '.aif' : 'audio/x-aiff', 4 ...
- 2019个人计划与Flag与期望
突然发现写博客是真的好. 希望未来能在其他地方写上日记. 总结2018中的个人缺陷: 1.忘掉了学习方法或者说学习方法不正确 2.偶尔就会去偷下懒,对自己不够严格,自控能力差. 3.心态虽比以前好很多 ...
- Python全栈开发:进程代码实例
进程与线程的关系 #!/usr/bin/env python # -*- coding;utf-8 -*- """ 多进程(主进程,子进程): 优点:能同时利用多个CPU ...
- SpringMVC参数绑定(未完待续)
1. Strut2与SpringMVC接收请求参数的区别 Struts2通过action类的成员变量接收SpringMVC通过controller方法的形参接收 2. SpringMVC参数绑定流程 ...
- csp-s模拟测试10.1(b)X 国的军队,排列组合, 回文题解
题面:https://www.cnblogs.com/Juve/articles/11615883.html X 国的军队: 好像有O(T*N)的直接贪心做法 其实多带一个log的二分也可以过 先对所 ...
- 暑期集训日志(Day0~Day5)
章·五:2019-07-15:明月不谙离恨苦,斜光到晓穿朱户 ·昨日小结: 昨天考试又是爆零边缘,除了难过就剩难过了. T1暴力打崩了只拿了5分. T2没给分时间.最后20分钟打了个残码.没仔细观察数 ...
- TF坐标变换
一.什么是TF 二.TF使用方法 三.TF包内的指令工具 四.相关API 1.广播变换发布坐标之间的坐标关系 #include <ros/ros.h> #include <tf ...