String、StringBuffer、StringBuilder原理详解

目录

1.String

1.1为什么String是不可变的

1.2 用 == 比较String对象

1.3 字符串的拼接 

1.3.1用 + 拼接,底层调用的是StringBuilder的append方法

1.3.2 用concat拼接

1.4 字符串的创建

2. AbstractStringBuilder

这个类是StringBuilder和StringBuffer的父类

3. StringBuffer (线程安全)

StringBuffer类继承了AbstractStringBuilder类,通过synchronized实现线程安全

3.1 StringBuffer的append(String str)方法

3.2 StringBuffer的toString()方法

3.3.StringBuffer创建对象

空参构造:字符数组初始长度为16

带参构造:字符数组初始长度为:16+字符串长度

4.StringBuilder (线程不安全)

StringBuilder类继承了AbstractStringBuilder类,没有synchronized,线程不安全

4.1 StringBuilder的一系列appen方法和toString()方法

5.用代码总结

5.1 关于拼接中null的总结:

5.2 关于new的总结:


1.String

1.1为什么String是不可变的

1.2 用 == 比较String对象


 

1.3 字符串的拼接 

public class String与StringBuffer {
    public static void main(String[] args) {
        /**
         * String的拼接
         */
        String ss = "abc";
        String s1 = ss.concat("de");
        System.out.println(s1);//abcde
        String s2 = ss + "ef";
        System.out.println(s2);//abcef
//        String s3 = ss.concat(null);NullPointerException
        String s4 = ss + null;
        System.out.println(s4);//abcnull,因为底层调用的是StringBuilder的append方法
    }
}

1.3.1用 + 拼接,底层调用的是StringBuilder的append方法,可以拼null

编译后:

1.3.2 用concat拼接,不能拼null(NullPointerException)

1.拼接的字符串如果为空,直接返回当前字符

2.创建一个新的字符数组,长度为当前字符串加上拼接的字符串,并把当前字符串拷贝进去

3.把拼接的字符串加到字符数组的后面,getChars -> arraycopy -> native方法

4.用字符数组创建新的字符串对象并返回

 

 

1.4 字符串的创建

public class String与StringBuffer {
    public static void main(String[] args) {
        String str = new String();
        System.out.println("!"+str+"!");//!!
    }
}

2. AbstractStringBuilder

这个类是StringBuilder和StringBuffer的父类

abstract class AbstractStringBuilder implements Appendable, CharSequence {

    char[] value;
    int count;

    AbstractStringBuilder() {
    }

    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

    @Override
    public int length() {
        return count;
    }

    public int capacity() {
        return value.length;
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    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;
    }

  
    public AbstractStringBuilder append(StringBuffer sb) {
        if (sb == null)
            return appendNull();
        int len = sb.length();
        ensureCapacityInternal(count + len);
        sb.getChars(0, len, value, count);
        count += len;
        return this;
    }

    private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }
}

3. StringBuffer (线程安全)

StringBuffer类继承了AbstractStringBuilder类,通过synchronized实现线程安全

 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
    private transient char[] toStringCache;

    //构造方法
    public StringBuffer() {
        super(16);//无参构造,字符数组初始容量为16
    }

    public StringBuffer(String str) {
        super(str.length() + 16);//参数是字符串的构造
        append(str);
    }

    @Override
//参数可以是:Object obj,String str,StringBuffer sb,AbstractStringBuilder asb,
//char[] str,boolean b,char c,int i,long lng,float f,double d
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

}

3.1 StringBuffer的append(String str)方法,可以拼null

1.调用父类AbstractStringBuilder的append(String str)的方法

2.拼接字符串是不是null,如果是null,走appedNull()方法

3.字符数组扩容,大小为count + len,再把原有的字符数组复制到里面去

4.把拼接的字符串加到字符数组的后面,getChars -> arraycopy -> native方法

跟String的concat不同的地方:这里直接操作的是value这个成员变量,并把这个字符数组返回,因此SringBuffer是可变的。而String是创建了一个新的String对象并返回。

public class String与StringBuffer {
    public static void main(String[] args) {
        /**
         * StringBuffer  线程安全的,用synchronized修饰了
         */

        //StringBuffer的append()方法
        StringBuffer sb4 = new StringBuffer();
        boolean b = false;
        sb4.append(b);
        System.out.println(sb4.toString());//false
        String sss = null;
        sb4.append(sss);
        System.out.println(sb4.toString());//falsenull
    }
}

3.2 StringBuffer的toString()方法


被transient修饰,不参与序列化和反序列化

3.3.StringBuffer创建对象

空参构造:字符数组初始长度为16

 带参构造:字符数组初始长度为:16+字符串长度

public class String {
    public static void main(String[] args) {
        StringBuffer sb3 = new StringBuffer();
        String s5 = sb3.toString();
        System.out.println("!" + s5 + "!");//!!
    }
}

4.StringBuilder (线程不安全)

StringBuilder类继承了AbstractStringBuilder类,没有synchronized,线程不安全

4.1 StringBuilder的一系列appen方法和toString()方法

一系列的append方法,调用的是父类AbstractStringBuilder 的方法

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{

    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

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

    public StringBuilder append(StringBuffer sb) {
        super.append(sb);
        return this;
    }

    @Override
    public StringBuilder append(CharSequence s) {
        super.append(s);
        return this;
    }

    @Override
    public StringBuilder append(CharSequence s, int start, int end) {
        super.append(s, start, end);
        return this;
    }

    @Override
    public StringBuilder append(char[] str) {
        super.append(str);
        return this;
    }

    @Override
    public StringBuilder append(char[] str, int offset, int len) {
        super.append(str, offset, len);
        return this;
    }

    @Override
    public StringBuilder append(boolean b) {
        super.append(b);
        return this;
    }

    @Override
    public StringBuilder append(char c) {
        super.append(c);
        return this;
    }

    @Override
    public StringBuilder append(int i) {
        super.append(i);
        return this;
    }

    @Override
    public StringBuilder append(long lng) {
        super.append(lng);
        return this;
    }

    @Override
    public StringBuilder append(float f) {
        super.append(f);
        return this;
    }

    @Override
    public StringBuilder append(double d) {
        super.append(d);
        return this;
    }

    @Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

}
 

5.代码总结

5.1 关于拼接中null的总结:

StringBuffer、StringBuilder可以append一个null

String不能concat一个null,会报空指针

String可以+null(底层调用的是StringBuilder的append方法)

5.2 关于new的总结:

如果是空参构造创建了一个String对象,初始化为""

如果是空参构造创建了StringBuffer或StringBuilder对象,初始化一个字符数组,长度是16

打印出来都是""


public class String与StringBuffer {
    public static void main(String[] args) {
        /**
         * String的拼接方法
         */
        String ss = "abc";
        String s1 = ss.concat("de");
        System.out.println(s1);//abcde
        String s2 = ss + "ef";
        System.out.println(s2);//abcef
//        String s3 = ss.concat(null);NullPointerException
        String s4 = ss + null;
        System.out.println(s4);//abcnull,因为底层调用的是StringBuilder的append方法
        String str = new String();
        System.out.println("!"+str+"!");//!!

        /**
         * String => StringBuffer
         */
        String s = "hello";
        //方式1:通过构造方法
        StringBuffer sb1 = new StringBuffer(s);
        System.out.println(sb1);//hello
        //方法2:通过append方法
        StringBuffer sb2 = new StringBuffer();
        sb2.append(s);
        System.out.println(sb2.toString());//hello


        /**
         * StringBuffer => String
         */
        StringBuffer buffer = new StringBuffer("world");
        //方法1:通过构造方法
        String str1 = new String(buffer);
        System.out.println(str1);//world
        //方法2:通过toString方法
        //任何引用类型调用toString方法都可以转成字符串
        String str2 = buffer.toString();
        System.out.println(str2);//world


        /**
         * StringBuffer  线程安全的,用synchronized修饰了
         */

        //StringBuffer的toString()方法
        StringBuffer sb3 = new StringBuffer();
        String s5 = sb3.toString();
        System.out.println("!" + s5 + "!");//!!

        //StringBuffer的append()方法
        StringBuffer sb4 = new StringBuffer();
        boolean b = false;
        sb4.append(b);
        System.out.println(sb4.toString());//false
        String sss = null;
        sb4.append(sss);
        System.out.println(sb4.toString());//falsenull


        /**
         * StringBuilder 线程不安全
         */
        StringBuilder sb5 = new StringBuilder();
        sb5.append(false);
        System.out.println(sb5.toString());//false
        String s6 = null;
        sb5.append(s6);
        System.out.println(sb5.toString());//falsenull
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值