String 和 StringBuff 都是有char数组组成,只是在处理方式上有不同。如何在不同情况下能更好使用它们。
String在java中是特殊的包装类,并且final类型的,通过final就知道它如果声明就不可改变的。
我想有人会说不对呀!
我这样不就改变了吗?
String s1 = "123123"
s1 =s1 + "abc";
System.out.println(s1);
输出结果:123123abc
实际上在jdk中String 处理方式是
String s1 = "123123" -> new char[s1.length];
s1 = s1+"abc"; -> s1 +new char["abc".length];
最后实际上s1的指针 是s1 +new char["abc".length];的地址 ,也就是讲它已经不是同一个对象了,这时总共产生了3个对象。
这3个对象的产生
String s1 = "123123" 创建过程首先会在String pool中找是否存在该对象,如果没有则会创建一个放到String pool,然后执行new String() ,这时就会将String pool对象copy到堆中,这时就生成了两个对象一个在String pool中,一个在堆中,String s1 引用指向堆.
s1 =s1 + "abc";
由于s1 不是常量当进行 s1 + "abc" ,这时就会new String(s1指向的内容+"abc"); 然后s1的引用在指向它
当字符串是固定长度的话使用String。
注意:如果在使用String拼接时可能会出现问题,并且在大量字符串拼接时有可能会出现内存溢出。
StringBuff 进行字符串拼接时,永远只会有一个StringBuff对象,并且线程是安全的。
在jdk源码中当我们new StringBuff();会默认给我们分配16长度
/**
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuffer() {
super(16);
}
当我们进行 buff.appen("asd");会判断StringBuff是否还有空间来容纳新的字符串,如果有直接加入,没有会在
(现有长度的基础上+1)*2。
StringBuff buff = new StringBuff();
//现在是15位没有超过默认大小16位,所以会直接将内容放入StringBuff对象中
buff.appen("012356789012345");
//在次加入的时候已经超过默认的长度,这时就会调用expandCapacity() 方法
int newCapacity = (value.length + 1) * 2;这句话就是在现有的长度的基础上增加StringBuff的容量,后面以此类推
buff.appen("67");
/**
* Appends the specified string to this character sequence.
* <p>
* The characters of the <code>String</code> argument are appended, in
* order, increasing the length of this sequence by the length of the
* argument. If <code>str</code> is <code>null</code>, then the four
* characters <code>"null"</code> are appended.
* <p>
* Let <i>n</i> be the length of this character sequence just prior to
* execution of the <code>append</code> method. Then the character at
* index <i>k</i> in the new character sequence is equal to the character
* at index <i>k</i> in the old character sequence, if <i>k</i> is less
* than <i>n</i>; otherwise, it is equal to the character at index
* <i>k-n</i> in the argument <code>str</code>.
*
* @param str a string.
* @return a reference to this object.
*/
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
if (len == 0) return this;
int newCount = count + len;
if (newCount > value.length)
expandCapacity(newCount);
str.getChars(0, len, value, count);
count = newCount;
return this;
}
/**
* This implements the expansion semantics of ensureCapacity with no
* size check or synchronization.
*/
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}