String的底层
String类没有提供用于修改字符串的方法。String类对象为不可变字符串,不可变字符串有一个优点:编译器可以让字符串实现共享。实际上只有字符串常量(使用“ ”声明,存储在字符串常量池中)是共享的,比较字符串值是否相等时使用equals()方法,不能使用==,==比较的是字符串的地址是否相同。如果字符串在常量池中,可以使用
==比较,因为指向的都是同一个字符串。下面是String的源代码,可以看到,String类是final修饰的,然后还有个成员属性 value 它也是final的并且是一个char类型的数组,通过构造方法可以看到,我们传递的参数值 是直接赋值给了 value
那么我们说明 String它是一个不可变字符串,底层是一个char类型的数组
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;
......此处省略N多代码
/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
}
直接使用” ”
声明的String对象会直接存储在常量池中,(可以实现共享)
String str1=”a”
jvm在运行时先查找常量池中是否有该字符串,如果有则直接返回该字符串的引用给first(实现了字符串 的共享) ;否则先在常量池中创建该字符串并返回引用。此时只会在常量池中创建String对象,不会在堆中创建。String str2=new String(“b”)
; 该代码生成了两个String对象。因为使用了“”会现在常量池中查找是否存在second对象,没有则创建,否则不创建;在常量池创建完成后,由于使用了new,jvm会在堆中创建内容相同的String对象,并将引用返回给str2.- String str3=”c”; String str4=str3+”d”;
运行时,+ 相当于new,所以堆中会有“cd”对象;常量池中会有”c” “d”两个对象,而不会有”c d ”对象。
StringBuffer
继承
StringBuffer
继承自AbstractStringBuilder
类
StringBuffer实现扩容
StringBuffer
扩容的机制在抽象类AbstractStringBuilder
中实现,当发现长度不够的时候(默认长度是16),会自动进行扩容工作,扩展为原数组长度的2倍加2,创建一个新的数组,并将数组的数据复制到新数组。
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
}
/**
* 确保value字符数组不会越界.重新new一个数组,引用指向value
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
/**
* 扩容:将长度扩展到之前大小的2倍+2
*/
private int newCapacity(int minCapacity) {
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
/**
* 判断大小,是否溢出
*/
private int hugeCapacity(int minCapacity) {
if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
线程安全性
几乎都是所有方法都加了synchronized
,几乎都是调用的父类的方法.,加锁,资源同步串行化处理,所以是线程安全的。
StringBuilder
@Override
public StringBuilder append(double d) {
super.append(d);
return this;
}
/**
* @since 1.5
*/
@Override
public StringBuilder appendCodePoint(int codePoint) {
super.appendCodePoint(codePoint);
return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuilder delete(int start, int end) {
super.delete(start, end);
return this;
}
-
方法中没有用
synchronized
修饰,线程非安全的字符串操作类 -
字符串的添加没有加同步处理,涉及到数组扩容,容易产生脏数据,破坏数据正确性
继承
StringBuilder继承自
AbstractStringBuilder`类
扩容
因为继承了抽象类AbstractStringBuilder
中实现,所以扩容与StringBuffer
的扩容机制相同,当发现长度不够的时候(默认长度是16),会自动进行扩容工作,扩展为原数组长度的2倍加2,创建一个新的数组,并将数组的数据复制到新数组。
执行速度
StringBuilder
> StringBuffer
> String