String这个类是Java中使用的最频繁的类之一,据本仔的不完全统计,这个类每月的使用量可饶地球…呃,三四五六圈,今天刚好用到了这个类,就简单的做个总结吧,让我们一起走进科学,探索神秘的String、StringBuilder以及StringBuffer的三兄弟
一、认识并了解String
想要熟悉一个类,最好的办法就是动动你的小手,点击查看这个类的实现源代码,String类的实现在\jdk1.6.0_14\src\java\lang\String.java 文件中。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
所以请你告诉我上面的内容, 你看出了什么?
真相(永远)只有一个しんじつbai)はdu いつも ひとつzhi
1.从这我们可以得出,String底层是一个final类型的字符数组,所以String的值是不可变的也即意味着String类不能被继承,并且它的成员方法都默认为final方法,所以说String是个字符串常量。在Java中,被final修饰的类是不允许被继承的,并且该类中的成员方法都默认为final方法。
2.上面列举出了String类中所有的成员属性,从上面可以看出String类其实是通过char数组来保存字符串的。
下面再继续看String类的一些方法实现:
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = count;
int i = -1;
char[] val = value; /* avoid getfield opcode */
int off = offset; /* avoid getfield opcode */
while (++i < len) {
if (val[off + i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0 ; j < i ; j++) {
buf[j] = val[off+j];
}
while (i < len) {
char c = val[off + i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(0, len, buf);
}
}
return this;
从上面的三个方法可以看出,无论是sub操、concat还是replace操作都不是在原有的字符串上进行的,而是重新生成了一个新的字符串对象。也就是说:每次对String的操作都会生成新的String对象,造成内存浪费
所以总结下来一点:
“对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象”。
二、String、StringBuffer以及StringBuilder的区别
1.简单来说,String是不可变对象,创建后便无法修改。修改实际是将引用指向了新的对象。而StringBuffer(和StringBuilder)是可变对象,他的内部有一个缓冲区,所以可以追加元素。查看源码我们可以看到:String的+ 都是通过调用StringBuilder的append()方法实现的,Java中"+"连接字符串对象时,会创建一个StringBuilder()对象并调用append()方法将数据拼接,最后调用toString()方法返回拼接好的字符串。
在这里,不得不说 StringBuilder 是一个牛逼的对象,String 对象底层是使用了
StringBuilder 对象的 append 方法进行字符串拼接的
2.遇到字符串处理优先考虑使用String。在实际开发中只有频繁修改内容才考虑使用StringBuffer类或StringBuilder类操作。查看源码你会发现,在StringBuffer类中定义的方法全部使用“synchronized”进行同步定义,属于安全的线程操作;而StringBuilder类没有同步定义,StringBuilder类的方法都是异步方法,属于非安全线程操作。
3.未完待续…
![](/qrcode.jpg)
三、String与StringBuffer的互相转换
1.将String转换为StringBuffer类对象
方式一:利用StringBuffer类的构造方法(public StringBuffer(String str))。接收String类对象,可以将String类对象实例化为StringBuffer类对象。
方式二:利用StringBuffer类中的append()方法(public StringBuffer append(String str))。利用append()方法像StringBuffer类中增加了一个String类对象,这样就相当于将String类对象转换为StringBuffer类对象。
2.将StringBuffer转换为String类对象
方式一:利用toString()方法可以将StringBuffer转换为String类对象实际上所有的类都会继承Object类的toString方法,所以所有的类对象都可以转换为String类对象。
方法二:利用String类的构造方法(public String(StringBuffer buffer))实现StringBuffer类与String类的转换。
睡了睡了~~~预知后事如何,且听下回熬夜