String StringBuffer StringBuilder 的区别

来源:互联网 发布:php程序员的发展方向 编辑:程序博客网 时间:2024/06/15 10:27

首先从执行效率上来说 String < StringBuffer < StringBuilder
有一种情况例外
一下情况 String a = “1”+”2” + “3” +”abc”; JVM会直接理解为 String a=”123abc”;

        String a = "1"+"2" + "3" +"abc";        System.out.println(a);        StringBuffer b = new StringBuffer("1")                 .append("2").append("3").append("abc");        System.out.println(b);

String 关键源码

 private final char value[];//final类型char数组

java 中的String 实际是用final修饰的字符数组,在String 执行过程中
每个String 标志位意味着 一次new 对象的操作,必须去内存中(栈)申请新的地址空间用于存放这个新的对象
这里用 == 操作符 比较String 和StringBuffer 的对象引用是否相同

        String a ="aaac";        String b = a + "bbb" ;        String c = a.replace("c","a");        //这里 a 和 b 是不同的对象引用        System.out.print(a == b);        System.out.println(a == c);        System.out.println("StringBuffer");        StringBuffer aa = new StringBuffer("aaa");        StringBuffer bb = aa.append("123");        StringBuffer cc = aa.replace(1,2,"c");        System.out.println(aa == bb);        System.out.println(aa == cc);        //这里 aa = bb = cc 同一对象引用

StringBuffer 关键源码:

  /**     * @since   JDK1.0.2     */    @Override    public synchronized StringBuffer reverse() {        toStringCache = null;        super.reverse();        return this;    }

可以看到很多 StringBuffer的方法都被加上了 synchronized ,即是多个对当前StringBuffer类的 某个 对象的 这些方法访问的时候 只有一个访问将被执行,其他的访问将被阻塞等待,也就是说 StringBuffer不存组线程安全的问题。
关于锁的问题
详见这位博主的博客

StringBuilder 源码与StringBuffer 源码一样 , 只是 StringBuffer 在每个方法前加上了 synchronized 。

StringBuilder 安全性测试代码:

public class testStringBuilder {    public static void main(String arg[]){        StringBuffer sbf = new StringBuffer();        StringBuilder sbi = new StringBuilder();        //10个 线程        for(int i = 0;i<10 ;i++){            new Thread(new TestThread(sbf,sbi)).start();        }    }}class TestThread implements Runnable{    StringBuffer sbf ;    StringBuilder sbi;    TestThread(StringBuffer sbf,StringBuilder sbi){        this.sbf = sbf;        this.sbi = sbi;    }    @Override    public void run() {        for (int i=0;i <10;i++){            try{                Thread.sleep(1);            }catch (InterruptedException e){                e.printStackTrace();            }            sbi.append("1");            sbf.append("1");            // sbi 会有遗失现象            System.out.println(sbi.length() + "/" + sbf.length());        }    }}