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源码解析的更多相关文章

  1. String,StringBuffer和StringBuilder源码解析[基于JDK6]

    最近指导几位新人,学习了一下String,StringBuffer和StringBuilder类,从反馈的结果来看,总体感觉学习的深度不够,没有读出东西.其实,JDK的源码是越读越有味的.下面总结一下 ...

  2. [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析

    String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识,  ...

  3. String、StringBuffer、StringBuilder源码分析

    利用反编译具体看看"+"的过程 1 public class Test 2 { 3 public static void main(String[] args) 4 { 5 int ...

  4. Stringbuffer与Stringbuilder源码学习和对比

    >>String/StringBuffer/StringBuilder的异同 (1)相同点观察源码会发现,三个类都是被final修饰的,是不可被继承的.(2)不同点String的对象是不可 ...

  5. String、StringBuffer、StringBuilder源码解读

    序 好长时间没有认真写博客了,过去的一年挺忙的.负责过数据库.线上运维环境.写代码.Code review等等东西挺多. 学习了不少多方面的东西,不过还是需要回归实际.加强内功,方能扛鼎. 去年学习M ...

  6. StringBuffer 和Stringbuilder源码分析

    首先看一下他们的继承关系   这个两个对象都继承了AbstractStringBuilder抽象类.   1.他们的实现方式都一样的,唯一区别的StringBuffer在多线程的时候是保证了数据安全, ...

  7. String的equals()方法源码解析

    每个String对象在创建的时候都构造了一个char类型的final声明的不可替换数组,数组中的每一个元素即字符串对应的每一个字符如图: String的equals()在比较的时候会进行两步比较: 1 ...

  8. String,StringBuffer和StringBuilder的异同

                                                                    String,StringBuffer和StringBuilder的异同 ...

  9. 小学徒成长系列—StringBuilder & StringBuffer关键源码解析

    在前面的博文<小学徒成长系列—String关键源码解析>和<小学徒进阶系列—JVM对String的处理>中,我们讲到了关于String的常用方法以及JVM对字符串常量Strin ...

随机推荐

  1. PHP面向对象编程题(方法的实践)

    <?php header('content-type:text/html;charset=utf-8'); /*设计一个peron类(有名字,年龄和蛋糕三个属性) 蛋糕一共1000块,是所有人共 ...

  2. 本地项目通过 git 同步到 github

    1. github创建仓库并克隆仓库地址 2. 在本地通过git命令:git clone <仓库地址> 生成github仓库文件夹 3. 将本地项目复制到该文件夹 4. 通过git命令:g ...

  3. Traveling by Stagecoach /// 状压DP oj22914

    题目大意: 输入n,m,p,a,b n是车票数(1<=n<=8),m是城市数(2<=m<=30) p是路径数(可能为0),a是起点,b是终点 接下来一行有n个数 为每张车票的马 ...

  4. 使用Math.random()函数生成n到m间的随机数字

    使用js生成n到m间的随机数字,主要目的是为后期的js生成验证码做准备,Math.random()函数返回0和1之间的伪随机数 讲解: 本文讲解如何使用js生成n到m间的随机数字,主要目的是为后期的j ...

  5. software database is broken解决办法

    ubuntu切换中文时报software database is broken错误. 网上的办法千篇一律,还都没有用.都是去应用中心删除thundbird之类的,啊....... 在终端下执行 sud ...

  6. [转]C#操作Excel初探

    近期一段时间正好在做winform导出Excel报表的问题,学习了一下C#操作Excel的一些方法(如:向Excel中插入图片:删除Excel指定sheet中的某行或某列,在Excel指定的单元格中画 ...

  7. SQL中的long text

    SQL中的long text 问题: 解决方法: SELECT CONVERT(VARCHAR(5000),参考文献) AS 参考文献 FROM tpi20160503 出现原因:

  8. LintCode刷题笔记-- A+B problem

    标签: 位运算 描述 Write a function that add two numbers A and B. You should not use + or any arithmetic ope ...

  9. Error-Idea:Process finished with exit code 1

    ylbtech-Error-Idea:Process finished with exit code 1 1.返回顶部 1. log4j:WARN No appenders could be foun ...

  10. codeforces 1129A2-Toy Train

    传送门:QAQQAQ 题意:有1-n个站点,成环形,有一辆运货车,在这个n个站点之间运输糖果,货车只能按照1->n的方向走,到第n个站的时候,又回到的1,现在告诉你有m个运输任务,从x站点运输一 ...