String&StringBuilder&StringBuffer详解

之前经常看到一个问题就是说到底String&StringBuilder&StringBuffer 有什么区别.究其原因 要需要看他们的源代码才可以清楚的明白是为什么

String类详解

下面这是对String类的描述:

String's Javadoc.JPG

打开源代码的时候你会发现String类是被final关键字修饰的
final修饰的变量会在class文件常量池中保存一个副本

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

    /**
     * Class String is special cased within the Serialization Stream Protocol.
     *
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];
...

1.可以注意到String类是final类,也就是说Stirng类不能被继承,而且所有的成员方法都默认为final方法. final是不允许被继承的
2.String是由一个char的数组来保存所谓的字符串的

    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }
    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

3.在String类返回类型是String的方法 都不是在原有的字符串上进行的,而是new了一个新的字符串对象.也就是说之前的字符串并没有进行改变.

重要的事情 -->>>
' 对String对象任何改变都不能影响到原来的object,相关的所有String的操作都要生成新的对象'
  1. String str = "abc";
    String str = new String("abc");
    上面两个语句有什么区别吗<有~>
    要考虑到编译的问题,在class文件中有一部分<class文件常量池>来储存编译期间生成的字面常量以及符号引用
        String str1 = "abc";
        String str2= "abc";
        String str3 = new String("abc");
        String str4 = new String("abc");
        System.out.println(str1 == str2 );
        System.out.println(str1 == str3 );
        System.out.println(str3 == str4 );
//Console结果
true
false
false

String str1 = "abc"; --->>> 但是同一个字符串只会定义一次,运行期间字面常量都会被储存到常量池里面.
在定义字面常量的时候 JVM会优先在常量池里查找是否有相同的字面常量,如果有就直接引用到已经存在的字面常量.如果没有找到就将在常量池里面开辟一个空间来储存这个新的字面常量,并将引用指向该字面常量.
String str3 = new String("abc"); --->>> 通过new关键字生成对象是在堆区(heap)进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的.因此通过new来创建出的一定是不同的对象,不管内容是否相同.

String StringBuilder StringBuffer区别?

既然String这么强大为什么还会要用StringBuilder或者StringBuffer呢?
String类不方便进行多次的数组操作 所以在进行多次的数据操作的时候就需要用到StringBuilder或者StringBuffer类中的方法进行操作.
接下来看一段代码

    public static void main(String args[]) {
        String string = "";
        for (int i = 0; i < 100 ; i++) {
            string += "hello";
        }
      }

在这里面累加的过程就是将原有的String变量指向的对象内容去除与"hello"进行字符串累加操作再存进另一个新的String对象中,再让string变量指向新生成的对象
在编译的字节码中其实每次循环的时候new了一个StringBuilder对象,再进行append()操作,最后再通过toString()返回String对象,也就是说在整个循环的过程中new了100个新的对象,其实并没有必要 这给JVM的GC带来了很多不必要的麻烦造成资源浪费.
事实上单单这一行代码string += "hello"; 已经被JVM自动优化为了

StringBuilder str = new StringBuilder();
str.append("hello");
str.toString();

但是同样的操作如果你使用 StringBuilder类

    public static void main(String args[]) {
        String str= new StringBuilder();
        for (int i = 0; i < 100 ; i++) {
            str.append( "hello)";
        }
      }

程序只进行了一次new操作,只生成了一个对象,append方法只是在现有的对象上操作并不会产生新的对象.所以在会进行多次操作的时候StringBuilder会比String性能好的多
那么问题来了StringBuilder StringBuffer有什么区别呢?
其实区别很小 只是StringBuffer类在成员方法的前面多了一个synchronized
为了在多线程操作的时候起到保护安全的

//StringBuilder
    @Override
    public StringBuilder reverse() {
        super.reverse();
        return this;
    }
//StringBuffer
    @Override
    public synchronized StringBuffer reverse() {
        toStringCache = null;
        super.reverse();
        return this;
    }
总结
1.当字符串操作或者改动相对较少的时候 使用String
2.当字符串操作或者改动相对较多的时候 使用StringBuilder 如果采用了多线程就使用StringBuffer
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容