string:不可变字符串,每次修改都回生成一个新的变量,浪费内存
StringBuilder:可变字符串 线程不安全,单线程操作效率高
StringBuffer:可变字符串 线程安全
package com.example.spring;
/**
* @Author: hyh
* @Date: 2022/2/22 14:57
**/
public class Test003 {
public static void main(String[] args) {
// 将 s1s1s1 放在常量池中 并返回引用
String s1 = "s1s1s1";
// 常量池中有 s1s1s1 直接返回引用
String s2 = "s1s1s1";
// 在堆内存开辟一块内存 并将该内存的value 值 指向常量池中的 s1s1s1
String s = new String(s1);
// 常量池中没有 在常量池中生成 333 并返回引用
s1 = "333";
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("123");
StringBuffer append1 = stringBuffer.append("123");
StringBuffer append2 = append1.append("321");
// append1 地址和 append2 地址是一样的
System.out.println(append1 == append2); // true
StringBuffer stringBuffer1 = new StringBuffer(16);
StringBuffer stringBuffer2 = new StringBuffer("123");
StringBuilder stringBuilder = new StringBuilder();
StringBuilder stringBuilder1 = new StringBuilder(16);
StringBuilder stringBuilder2 = new StringBuilder("456");
stringBuilder.append("456");
}
}
// String 源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
// final 数组
private final char value[];
// 当 new 一个字符串时 实际给的时value 数组,而且时final 修饰,不可更改
public String() {
this.value = "".value;
}
// 第一次 stringBuilder.append("456"); srcBegin = 0, srcEnd = 3, dst[] = value[], dstBegin = 0
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
// str.getChars(0, len, value, count); 由于调用的是 str 所以此时的value 就是str 的value str = "456"
// 将 str = "456" 从0 开始 复制到 dst = value[] 从0 开始 复制 3 - 0 = 3 个元素
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
}
// StringBuffer 源码 父类是 AbstractStringBuilder
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
//
private transient char[] toStringCache;
// new StringBuffer();
public StringBuffer() {
// 调用父类方法 并给初始大小为16
super(16);
}
// new StringBuffer(16);
public StringBuffer(int capacity) {
super(capacity);
}
// new StringBuffer("123");
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
// synchronized 该方法被加同步锁了 这也是线程安全的原因,后面和 Stringbuilder.append() 方法几乎一样
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
}
// StringBuilder StringBuffer 的父类
abstract class AbstractStringBuilder implements Appendable, CharSequence {
// 数组 没有final修饰
char[] value;
// 存储元素的个数 实际元素数量
int count;
AbstractStringBuilder() {
}
// 调用父类方法 并给初始大小为16
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
// append 方法
public AbstractStringBuilder append(String str) {
// 追加字符串为 null 直接返回
if (str == null)
return appendNull();
// 第一次 stringBuilder.append("456"); len = 3
int len = str.length();
// 第一次 count = 0 len = 3
ensureCapacityInternal(count + len);
// 调用 String类 的 getChars() 方法
str.getChars(0, len, value, count);
// 此时 value[] 已经被复制了 456 元素 count = 0+3 此时表示 value 数组实际有3个元素
count += len;
// 返回当前对象
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// 第一次 value 初始化大小为 16 3-16 < 0 不进入方法
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
}
// StringBuilder 源码 父类是 AbstractStringBuilder
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
// new StringBuilder() 和 new StringBuffer() 一样
public StringBuilder() {
super(16);
}
// new StringBuilder(16);
public StringBuilder(int capacity) {
super(capacity);
}
// new StringBuilder("456");
public StringBuilder(String str) {
// 调用父类方法 并传入初始大小 为 3("456")+ 16
super(str.length() + 16);
append(str);
}
@Override
public StringBuilder append(String str) {
// 调用父类方法 第一次 stringBuilder.append("456");
super.append(str);
return this;
}
}