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, 0);
    }

    public int indexOf(String str, int fromIndex) {
        return indexOf(value, 0, value.length,
                str.value, 0, 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 == 0 ? sourceCount : -1);
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        if (targetCount == 0) {
            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 + 1;
                int end = j + targetCount - 1;
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);

                if (j == end) {
                    /* Found whole string. */
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }

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 = 0;
        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 - 8;
  • 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(0, len, value, count);
        count += len;
        return this;
    }

    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? 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, 0, 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类型

原文地址:https://www.cnblogs.com/yxth/p/11443707.html

时间: 2024-10-20 04:15:13

String、StringBuffer和StringBuilder源码解析的相关文章

String,StringBuffer和StringBuilder的异同

                                                                String,StringBuffer和StringBuilder的异同 String,StringBuffer和StringBuilder的的源码已经在本博客的JDK源码学习系列中有了详细的介绍: String 源码: http://blog.csdn.net/sheepmu/article/details/23303837 StringBuffer 和StringB

String、StringBuilder、 StringBuffer 深入分析 源码解析

java学习有一段时间了,但学习的东西都是框架等东西,java基础知识有点遗忘,所以重温一下java基础知识,写写文章里面有错的希望大家指正共同进步~~ 一.String 大家经常会说使用"+"号连接String 字符串比StringBuffer慢,String类对象为不可变对象,一旦你修改了String对象的值,隐性重新创建了一个新的对象,那接下来我们详细分析一下为什么使用"+"号速度会慢,为什么String 对象是不可变对象: 1.final修饰类.引用变量.基

[源码]String StringBuffer StringBudlider(2)StringBuffer StringBuilder源码分析

纵骑横飞 章仕烜 昨天比较忙 今天把StringBuffer StringBulider的源码分析 献上 在讲 StringBuffer StringBuilder 之前 ,我们先看一下 它们共同的老祖宗 AbstractStringBuilder 这是 StringBuilder StringBuffer 的根基 再看看 这两个实现类 里边有什么 很显然,这两个东西什么都没写吧 我们看看 另一个门派的 String 看出 为什么 我们说String 对象是不可变的 StringBuilder

String源码解析(一)

本篇文章内的方法介绍,在方法的上面的注释讲解的很清楚,这里只阐述一些要点. Java中的String类的定义如下: 1 public final class String 2 implements java.io.Serializable, Comparable<String>, CharSequence { ...} 可以看到,String是final的,而且继承了Serializable.Comparable和CharSequence接口. 正是因为这个特性,字符串对象可以被共享,例如下面

Java String源码解析

String类概要 所有的字符串字面量都属于String类,String对象创建后不可改变,因此可以缓存共享,StringBuilder,StringBuffer是可变的实现 String类提供了操作字符序列中单个字符的方法,比如有比较字符串,搜索字符串等 Java语言提供了对字符串连接运算符的特别支持(+),该符号也可用于将其他类型转换成字符串. 字符串的连接实际上是通过StringBuffer或者StringBuilder的append()方法来实现的 一般情况下,传递一个空参数在这类构造函

String源码解析

定义 先看一下文档中的注释 12345 * Strings are constant; their values cannot be changed after they * are created. String buffers support mutable strings. * Because String objects are immutable they can be shared. */ String对象是常量,创建之后就不能被修改,所以该对象可以被多线程共享. 123456789

死磕 Java 系列(一)&mdash;&mdash; 常用类(1) String 源码解析

写在前面 这是博主新开的一个 java 学习系列,听名字就可以看出来,在这一些系列中,我们学习的知识点不再是蜻蜓点水,而是深入底层,深入源码.由此,学习过程中我们要带着一股钻劲儿,对我们不懂的知识充满质疑,力求把我们学过的知识点都搞清楚,想明白. 一.引言 在 java 的世界里,存在一种特殊的类,它们的创建方式极为特别,不需要用到 new XXX(当然也可以用这种方式创建), 但是却大量出现在我们的代码中,那就是 String 类.作为日常中使用频率最高的类,它是那么普通,普通到我们从来都不会

Android研发中对String的思考(源码分析)

1.常用创建方式思考: String text = "this is a test text "; 上面这一句话实际上是执行了三件事 1.声明变量 String text; 2.在内存中开辟空间 (内存空间一) 3.将变量的text的引用指向开辟的内存空间 当有 text = "this is a change text"; 这一句话执行了两件事 1.在内存中开辟空间 2.将变量text 的引用指向 新开辟的内存空间 3.内存空间一此时依然存在,这就是说明了Stri

JDK源码及其他框架源码解析随笔地址导航

置顶一篇文章,主要是整理一下写过的JDK中各个类的源码解析以及其他框架源码解析的文章,方便自己随时阅读也方便网友朋友们阅读及指正 基础篇 从为什么String=String谈到StringBuilder和StringBuffer Java语法糖1:可变长度参数以及foreach循环原理 Java语法糖2:自动装箱和自动拆箱 集合篇 图解集合1:ArrayList 图解集合2:LinkedList 图解集合3:CopyOnWriteArrayList 图解集合4:HashMap 图解集合5:不正确