String,StringBuffer和StringBuilder的区别是面试中高频出现的问题,很多有开发经验的程序员,如果不注意,也不知道其中的一些区别,今天我们就来谈谈这三者的区别。
一 Java String 类
字符串,我们经常会用到,Java中字符串属于对象,Java提供了String类来创建和操作字符串。底层是char型数组。
但是特别关注的是字符串是不可变的,这就导致我们每次对String的操作都会重新创建String对象,这样不仅效率低下,而且频繁创建导致内存的浪费。
我们可以看到,初始化str为“hello”,此时需要分配一次地址给str,在str后面加上字符串“world”,此时为“world”开辟内存空间。最终的“hello world”还要分配一次内存空间。这样简单的一个字符串相加,需要分配三次内存,不得不说是对内存的极大浪费。
为了解决这个问题,我们就需要Java 为我们提供的两个类StringBuffer和StringBulder.
二 StringBuffer和StringBulder
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
我们可以先看一下两者的继承关系:
我们可以看到StringBuffer和StringBuilder所继承和实现的类都是相同的。查看源码可以看到,两者提供的方法也基本相同。
StringBuffer在方法前添加了synchronized
关键字来实现线程安全,而StringBuilder是线程不安全的。
这三者的底层都是使用char[]存储,如
String str = new String() //底层会是 new char[];
String str = new String("abc") // 底层会 用new char[]{'a','b','c'};存储
但是对于StringBuffer, StringBuffer sb = new StringBuffer()我们查看底层源码:
/**
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuffer() {
super(16);
}
//调用父类的构造方法,创建一个长度为16的 char[16]。
StringBuffer和StringBuilder长度是可变的,这一点我们可以通过AbstractStringBuilder的newCapacity方法可以看出:
/**
* Returns a capacity at least as large as the given minimum capacity.
* Returns the current capacity increased by the same amount + 2 if
* that suffices.
* Will not return a capacity greater than {@code MAX_ARRAY_SIZE}
* unless the given minimum capacity is greater than that.
*
* @param minCapacity the desired minimum capacity
* @throws OutOfMemoryError if minCapacity is less than zero or
* greater than Integer.MAX_VALUE
*/
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
三 总结
- String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间
- StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量
- StringBuilder可变类,速度更快,线程不安全,单线程使用