当前位置:   article > 正文

java进阶-第五讲 StringBuilder 和 StringBuffer_java同一个方法中stingbuffer只能用一次吗

java同一个方法中stingbuffer只能用一次吗

java进阶-第五讲 StringBuilder 和 StringBuffer

1 StringBuilder与String的区别

String和StringBuilder的底层都是char数组
但是String的char[] 是final修饰的,只能被赋值一次
StringBuilder的char[]数组没有final修饰,是可以被多次赋值的
在StringBuilder中char[] value的赋值,实际上是给StringBuilder构造出来的字符串进行内容的改变。
改变内容是通过数组的扩容,然后指向扩容后的数组来改变数组的内容,从而达到改变字符串内容的效果。
String类型的字符串,一旦定义就不可以改变。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2 StringBuilder的构造方法

// 无参构造
public StringBuilder() {
        super(16);
    }
无参构造的实现,给我们一个什么信息?
    1. StringBuilder的父类是AbstractStringBuilder
    2. 它的构造方法直接调用了父类的有参构造
    3. 父类的有参构造原型应该是:
    	public AbstractStringBuilder(int capacity) {
    		this.value = new char[capacity];	
		}
	4. super(16)告诉我们,无参的StringBuilder()构造出来的StringBuider对象
        中,char[] value数组的初始大小是:16
        这样就是说,StringBuilder默认的字符串长度是16
        
 // String类型的对象作为参数
public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }
如果传入的是字符串,那么构造出来的字符串长度应该是传入的 字符串长度+16
补充:
    java1.9以后,String和StringBuffer、StringBuilder的底层都由原来的char[]数组变成了byte[]数组。
    为什么要这么做?底层有char[] 改成byte[]有什么用?节省了一半的空间。节省空间。
    
StringBuilder中:    
    底层的char[] value,问,该数组的作用是什么?
    1.char[] value数组在StringBuilder中,就是一个缓存。
    2.它可以被多次赋值,但只能指向一个数组对象
    3.一旦改变它的指向,原来指向的那个数组对象被GC回收。
    4.所以,不论怎么追加字符,改变字符串的内容长度,实际上是这样的:
     在原来数组的大小之上建立新数组
     将原来数组的内容拷贝到新数组中
     将追加的内容放入新数组中
     将引用指向新的数组
     原来的数组被回收
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

3 字符串的拼接

在日常开发中,大家往往喜欢对字符串进行拼接。
String str = "12";
String str1 = str + "3";
str1 = str1 + "4";
这样做不好,浪费空间。实际对于开者来说,只是想要具体的结果。
这种做法浪费存储空间。
正确的做法是通过StringBuilder或者是StringBuffer来进行字符串的拼接
因为StringBuilder和StringBuffer底层有一个字符缓存数组。
追加的字符串,不会直接放入字符串常量池中。会先放入堆中的字符数组中。
直到调用toString方法才将最后的结果一次性存入到方法区内存中的字符串常量池中。
因为,只有String类型的才存放到常量池中。
StringBuilder和StringBuffer,不是String类型的。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
public class StringBufferTest01 {

    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("abc");
        System.out.println(stringBuilder.capacity());

        stringBuilder.append("d"); // abcd
        stringBuilder.append("e");// abcde
        stringBuilder.append("f");// abcdef
        stringBuilder.append("g"); // abcdfeg
// "abc" d e f g abcdefg
        System.out.println(stringBuilder);

        String str = "abc";
        String str1 = str + "d";
        str1 = str1 + "e";
        str1 = str1 + "f";
        str1 = str1 + "g";

//     abc abcd abcde abcdef abcdefg d e f g
    }
}

在以后开发过程中,使用到字符串的时候,推荐使用 String = "xxx"
在进行字符串拼接的时候,尽量少使用"+"去拼接,而是通过StringBuilder或者是StringBuffer
    中的append()方法来进行字符串的拼接。
    源码追踪图如下:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述

  • 关于StringBuilder中的toString()方法
 @Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);// value.length = 16
        
    }

// Create a copy, don't share the array 重新创建了一个String对象。不是共享。
// 这个方法被调用以后,方法区内存中的字符串常量池里才会有一个String常量。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 关于println()的理解
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("d");
System.out.println(stringBuilder);// Object类型
System.out.println(stringBuilder.toString());// String类型
// 上面两个不是一回事

String string = "a";
System.out.println(string);/// String类型
System.out.println(string.toString());// String类型
// 这两个才是一回事
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • String和StringBuilder
他们不是一回事,StringBuilder构造出来的是StringBuilder的对象,这个对象只有toString()之后,才是String类型的字符串。
所以StringBuilder构造出来的对象,不会放在方法区字符串常量池中。只有当他调用toString方法的时候,才会被转换为字符串,字符串最后都会放入到方法区内存的字符串常量池中。

我们不希望,常量池不断地被占用,如果用字符串直接拼接的方式,是不好,这样会造成常量池内存空间的大量占用。那么我们可以使用StringBuilder和StringBuffer来进行字符串的拼接,最后再将他们toString之后,将最后的那一个结果放入到常量池中。这样做节省常量池的空间。

什么时候使用StringBuilder?

/*  
String string1 = "中华人民共和国";
String lr = "湖南省长沙市" + string1;
String xr = "新疆自治区" + string1;

address(lr);
*/

StringBuilder st = new StringBuilder("中华人民共和国");
StringBuilder zhangjiajie = st.append("湖南省长沙市");
// "中华人民共和国湖南省长沙市" --- 这个拼接后的结果存在于堆中,它是StringBuilder对象
// 它不是String对象。要将它转成String对象,只有一个方式,调用toString()方法。
// 调用了toString方法以后,实际是在底层通过StringBuilder的char[] value,
// 和数组中的内容创建了一个新的String对象。
String lr = zhangjiajie.toString();
address(lr);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

4 StringBuilder 和 StringBuffer的区别

  • StringBuffer是线程安全的

  • StringBuilder不是线程安全的

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/657461
推荐阅读
相关标签
  

闽ICP备14008679号