StringBuffer的作用是什么呢?
我们知道String是final类型的,是不可变的对象,我们如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,不仅耗时,而且还浪费空间。但是使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用,节省了内存。因此在字符串需要经常改变内容的时候,我们通常不适用String,而是使用StringBuffer。
String和StringBuffer之间如何相互转换?
1、把String转换为StringBuffer:
//法一:通过构造函数
String s = "hello";
StringBuffer sb = new StringBuffer(s);
//法二:通过append()方法
String s = "hello";
StringBuffer sb2 = new StringBuffer();
sb2.append(s);
2、把StringBuffer转换成String
StringBuffer sb2 = new StringBuffer("love you baby");
sb2.append("假的呢");
String str1 = new String(sb2); //法一:通过构造方法
String str2 = sb2.toString(); //法二:通过toString()方法
注意:不可以把字符串直接赋值给StringBuffer
StringBuilder和StringBuffer的区别是什么?
java.lang 类 StringBuffer:线程安全的可变字符序列。
public final class StringBuffer extends Object implements Serializable, CharSequence
java.lang 类 StringBuilder:线程不安全的可变的字符序列。
public final class StringBuilder extends Object implements Serializable, CharSequence
StringBuilder提供一个与 StringBuffer 兼容的 API,也就是他们的用法都是一样的。他们的唯一区别就是StringBuilder不保证同步,线程不安全,但是速度快。因此StringBuilder类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候,因为在大多数实现中,它比 StringBuffer 要快。
String、StringBuffer、StringBuilder的区别是什么呢?
1、String是内容不可变的,而StringBuilder、StringBuffer都是内容可变的。
2、StringBuffer是同步的,数据安全,效率低
3、StringBuilder是不同步的,数据不安全,效率高。
StringBuffer和数组的区别是什么?
都可以看成一个容器,用来装其他的数据。但是StringBuffer的数据最终都会变成一个字符串数据。
而数组可以放置多种数据,比如int型数组、String类型数组、char类型数组等。但数组内部的数据必须是同一种数据类型。
String作为参数传递和StringBuffer作为参数传递有什么区别?
形式参数:
基本类型:形式参数的改变不影响实际参数
引用类型:形式参数的改变直接影响实际参数
public class StringBufferDemo {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "you";
System.out.println(s1 + "---" + s2); // hello----you
change(s1, s2);
System.out.println(s1 + "---" + s2); // hello----you
StringBuffer sb1 = new StringBuffer("hello");
StringBuffer sb2 = new StringBuffer("you");
System.out.println(sb1 + "---" + sb2); // hello---you
change(sb1, sb2);
System.out.println(sb1 + "---" + sb2); // hello----youyou
}
private static void change(StringBuffer sb1, StringBuffer sb2) {
sb1 = sb2;
sb2.append(sb1);
}
private static void change(String s1, String s2) {
s1 = s2;
s2 = s1 + s2;
}
}
字符串是常量值,它是一种特殊的引用类型(在这里可以把它当做基本类型来看),它的形参改变对实参没有影响。
而对于StringBuffer的change()方法中直接赋值sb1 = sb2是不会影响sb1的,只有调用append()方法才会影响。
我们可以通过断点调试来看其中的细节:
StringBuffer的一些方法:
StringBuffer() :构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符。
StringBuffer sb = new StringBuffer();
System.out.println("sb:" + sb); //sb:
System.out.println("sb.capacity():"+sb.capacity()); //sb.capacity():16
System.out.println("sb.length():"+sb.length()); //sb.length():0
StringBuffer(int capacity) :构造一个不带字符,但具有指定初始容量的字符串缓冲区。
StringBuffer sb1 = new StringBuffer(50);
System.out.println("sb1:" + sb1); //sb1:
System.out.println("sb1.capacity():"+sb1.capacity()); //sb1.capacity():50
System.out.println("sb1.length():"+sb1.length()); //sb1.length():0
StringBuffer(String str) :构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
StringBuffer sb2 = new StringBuffer("helloya");
System.out.println("sb2:" + sb2); //sb2:helloya
System.out.println("sb2.capacity():"+sb2.capacity()); //sb2.capacity():23
System.out.println("sb2.length():"+sb2.length()); //sb2.length():7
输出:这里的容量为什么是23呢?23=16+7,初始容量+字符串的长度。看下面的源码就更清楚了。
public int capacity():返回当前容量。容量指可用于最新插入的字符的存储量,超过这一容量就需要再次进行分配。
public int length():返回长度(字符数)。
我们可以看一下不同的构造方法对应的源码,方便我们理解容量的概念。
public StringBuffer() {
super(16);
}
public StringBuffer(int capacity) {
super(capacity);
}
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public StringBuffer append(String str):可以把任意类型数据添加到字符串缓冲区里面。并返回字符串缓冲区本身
无论是boolean还是int等其他类型的参数,参数都将被转换成字符串,就好象使用了 String.valueOf 方法一样。然后,将所得字符串中的字符追加到此序列。
注意:进行append方法拼接之后返回的是字符串缓冲区本身。
StringBuffer sb = new StringBuffer();
StringBuffer sb1 = sb.append("hello");
StringBuffer sb2 = sb.append(123);
sb.append(true).append(34.12).append("hi");
System.out.println("sb:" + sb); //sb:hello123true34.12hi
System.out.println("sb1:" + sb1); //sb1:hello123true34.12hi
System.out.println("sb2:" + sb2); //sb2:hello123true34.12hi
System.out.println(sb == sb1); //true
System.out.println(sb == sb2); //true
public StringBuffer insert(int offset,String str):将字符串插入此字符序列中。
按顺序将 String 参数中的字符插入此序列中的指定位置,将该位置处原来的字符向后移,此序列将增加该参数的长度。如果 str 为 null,则向此序列中追加 4 个字符 “null”。
可以将任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身。
StringBuffer sb = new StringBuffer();
sb.insert(0, "null");
System.out.println(sb); //null
sb.insert(1, "hehe");
System.out.println(sb); //nheheull
public StringBuffer deleteCharAt(int index):删除指定位置值的字符,并返回字符串缓冲区本身。
StringBuffer sb = new StringBuffer();
sb.append("hello").append("girl!");
sb.deleteCharAt(1); // 删除字符e
sb.deleteCharAt(1); // 删除字符l(因为上面的e已经被删除了,因此l字符就跑到了索引为1的位置上了)
System.out.println(sb); //hlogirl!
public StringBuffer delete(int start, int end):移除此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符,如果不存在这种字符,则一直到序列尾部。如果 start 等于 end,则不发生任何更改。
StringBuffer sb = new StringBuffer();
sb.append("hello").append("girl!");
sb.delete(5, 9); //删除girl这个单词
System.out.println("sb:"+sb); //sb:hello!
sb.delete(0, sb.length()); //删除所有数据
System.out.println("sb:"+sb); //sb:
public StringBuffer replace(int start,int end, String str):使用给定 str 替换此序列从指定的 start 处开始,一直到索引 end - 1 处的字符,如果不存在这种字符,则一直到序列尾部。先将子字符串中的字符移除,然后将指定的 String 插入 start。(如果需要,序列将延长以适应指定的字符串。)
StringBuffer sb = new StringBuffer();
sb.append("hello").append("girl!");
sb.replace(0, 5, "hi"); // 把hello替换成hi
System.out.println("sb:" + sb); // sb:higirl!
public StringBuffer reverse()将此字符序列用其反转形式取代。
StringBuffer sb = new StringBuffer();
sb.append("hello").append("girl!");
sb.reverse();
System.out.println("sb:" + sb); //sb:!lrigolleh
public String substring(int start):返回一个新的 String,它包含此字符序列当前所包含的字符子序列。该子字符串始于指定索引处的字符,一直到此字符串末尾。 注意:返回的是一个String,但是字符串缓冲区本身不变的。
StringBuffer sb = new StringBuffer();
sb.append("hello").append("girl!");
String str = sb.substring(5);
System.out.println("str:"+str); //girl!
System.out.println("sb:" + sb); //sb:hellogirl!
public String substring(int start, int end)返回一个新的 String,它包含此序列当前所包含的字符子序列。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符。
用法同上。我就不举例了。