JAVA基础01-String,StringBuffer和StringBuilder
java 基础中字符串用到最多的就是String,StringBuffer和StringBuilder,这三个也是面试中最常问到的,三者之间的异同,其实实际工作中,我们大致知道使用场景,但是要用理论话的语言去总结,总是比较麻烦。
1.String
1.1继承实现关系

1.2 源码分析
- 1> final 修饰的类无法被继承
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
- 2> String的数据存放在final修饰的char数组中,所以String对象初始化之后值不能改
private final char value[];
- 3> String 值比较,总共两种方式,一种是继承了Comparable接口,实现compareTo()方法通过逐个字符串比较;另一种方法是,compareToIgnoreCase() 方法,通过静态成员类,实现Comparator方法,逐个char变大写比较,变小写比较;
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
- 4> 字符串之间的关联,String提供了静态的方法,可以将多个字符串通过delimiter进行拼接;
public static String join(CharSequence delimiter, CharSequence... elements) {}
5>字符串的trim()方法,对字符串双端去空
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
2.AbstractStringBuilder
2.1 继承实现关系
2.2源码分析
- 1>初始长度设置,通过构造方法:数据存储在非fianl的char数组中,通过构造函数传参初始化;
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
- 2>.在append的时候,char[]数组进行扩容,一般是现有值长度的2倍+2
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;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {//最小长度大于现有长度时,进行扩容
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));//复制生成新的char[]数组
}
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;//容量编程 现有长度的2倍+2
if (newCapacity - minCapacity < 0) { //扩容后还是小于最小长度时,将最小长度赋值给扩容长度
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
3.StringBuilder
1.源码分析
1> final修饰的类,不可以继承
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
2> 默认初始长度为16
public StringBuilder() {
super(16);
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
3>转成字符串toString()方法是生成新的String对象
@Override
public String toString() {
return new String(value, 0 , count);
4.StringBuffer
1.源码分析
1> final修饰不可继承
public final class StringBuffer
2> toString缓存数据;
1.通过一个transient修饰的字段toStringCache,进行转字符串存储;
2.在每个值改变的操作将toStringCache设置为空;
3.在toString()方法中,如果toStringCache为空,就copy新的char[]数组赋值给toStringCache ;
4.如果StringBuffer中的数值没变动,调用toString方法的时候,直接调用toStringCache就可以了;
private transient char[] toStringCache;
@Override
public synchronized StringBuffer append(long lng) {
toStringCache = null;
super.append(lng);
return this;
}
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
通过上面的可以知道,如下:
相同点:
1.都是final类,不可以继承;
2.内部存取数据的都是char数组;
3.都实现了CharSequeue,可以对字符串进行相关操作;
不同点:
1.String 和StringBuilder,StringBuffer的区别:
- 1. String的值final 数组,赋值后不可改变;StringBuilder,StringBuffer 非final char数组,初始化后可以改变值;
- 2. String的字符拼接,每拼接一次,相当于生成一个新的字符串;StringBuilder,StringBuffer通过给内部的char数组扩容,不用生成新的对象,效率更高;
- 3. char数组初始长度都是16 ;
- 2.StringBuilder 和 StringBuffer 之间的区别:
- 1. StringBuffer的所有操作都加synchorinized,因此是线程安全的;
- 2. StringBuffer的toString方法,有缓存,多次toString效率更高;
- 3.StringBuilder 效率更高,但是线程不安全;
常见问题:
- 1.自己写一个String,或StringBuilder类可以替换原有的JDK的String么?
答:这个问题其实和String,StringBuilder没关系了,而涉及到的是JVM类加载中,双亲委派模型;
双亲委派模型,是类加载器接收到当前类的加载请求,并不会直接去加载,而是逐级向父加载器发送请求,当父加载器没有相关的类,当前子加载器才自行加载;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示