zoukankan      html  css  js  c++  java
  • Java中String,StringBuffer,StringBuilder的区别及其使用

    由于笔试面试经常会问到这个问题,所以在这里先把这些问题搞清楚。

    String:自JDK1.0开始即有,源码中对String的描述:

      "Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings."

    由此我们可知String是常量,一个String对象一旦被创建它的值就不能改变,所以如果你创建了一个String对象,然后改变了它的值,实际上是指,你创建了两个String对象。然后把引用指向你新创建的String对象。

    从这里我们可以得知:如果你要经常改变一个字符串的值,最好不要用String类,因为每改变一次就创造一个新的对象,然后旧的对象不仅占用着内存,并且还没有被用到,这样会造成内存的极大浪费,从而对程序的性能造成影响。当然这些无引用的对象最终会被JVM的GC机制所回收。

    StringBuffer:自JDK1.0开始即有,源码中对StringBuffer的描述:

      "A thread-safe, mutable sequence of characters. " 一个线程安全的,可变的字符串序列

    所以,StringBuffer是线程安全的,它的内容可变的变量。尽管它的内部也是用字符串数组来存储字符串的值,但是它和String在构造方法上面有所不同:

    String的无参构造方法:

    public String() {
        this.offset = 0;
        this.count = 0;
        this.value = new char[0];
        }

    StringBuffer的无参构造方法:

    public StringBuffer() {
        super(16);
        }
    
    AbstractStringBuilder(int capacity) {
            value = new char[capacity];
        }

    其中StringBuffer继承了AbstractStringBuilder,并调用AbstractStringBuilder的构造方法,这里,我们可以知道,它先预留了16个字节的空间。而String则没有预留空间。

    况且,StringBuffer还可以指定初始预留的空间大小。

    再来看含参构造方法

    String:

    public String(String original) {
        int size = original.count;
        char[] originalValue = original.value;
        char[] v;
          if (originalValue.length > size) {
             // The array representing the String is bigger than the new
             // String itself.  Perhaps this constructor is being called
             // in order to trim the baggage, so make a copy of the array.
                int off = original.offset;
                v = Arrays.copyOfRange(originalValue, off, off+size);
         } else {
             // The array representing the String is the same
             // size as the String, so no point in making a copy.
            v = originalValue;
         }
        this.offset = 0;
        this.count = size;
        this.value = v;
        }

    StringBuffer的构造方法:

     public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
        }

    而append方法则调用父类AbstractStringBuilder的append方法,这个方法是线程安全的,这里不再贴源代码,顺便说一句,StringBuilder和StringBuffer之间的区别就是:一个是线程安全的,一个不是线程安全的,他们的append方法都是调用AbstractStringBuilder的append方法,但是,请看:

    StringBuffer的append:

    public synchronized StringBuffer append(String str) {
        super.append(str);
            return this;
        }

    StringBuilder的append:

     public StringBuilder append(String str) {
        super.append(str);
            return this;
        }

    而两者的super.append(str)均为:

     public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
            int len = str.length();
        if (len == 0) return this;
        int newCount = count + len;
        if (newCount > value.length)
            expandCapacity(newCount);
        str.getChars(0, len, value, count);
        count = newCount;
        return this;
        }

    由于我们主要是讨论区别,具体append的解释就不说了,大家可以自身查看源代码。

    StringBuilder:自JDK1.5之后才有。

    源代码中的描述:"A mutable sequence of characters. This class provides an API compatible

     with <code>StringBuffer</code>, but with no guarantee of synchronization.

    "

    它和StringBuffer的API是兼容的,但是不保证同步。

    所以,综上所述,我们可以得出结论:在多线程条件下,如果对字符串的同步性要求严格,而且字符串经常改变,则应该用StringBuffer较为合理,而StringBuilder则比较适用于对同步性要求不那么严格,并且字符串经常要改变的程序中。如果该字符串几百年不用改变一次,那么肯定是用String比较合理了。

    /** 原创作品,转载请注明出处,如发现本文中有任何错误或有不同看法,热烈欢迎评论交流^_^ **/

  • 相关阅读:
    Redis持久化
    环境搭建
    openresty了解基础
    正向代理和反向代理
    Java IO流:(十)字节缓冲流
    Java IO流:(九)缓冲流
    第二节:MySQL软件的卸载(Windows版)
    第一节:MySQL产品的介绍
    第一节:数据库相关知识
    MySQL【目录】
  • 原文地址:https://www.cnblogs.com/iceseal/p/3597670.html
Copyright © 2011-2022 走看看