Java中的String、StringBuffer和StringBuilder

字符串在我们的实际编程中是接触很多的,但是,一学到这就感觉头有点大。首先说下我遇到的问题吧。

1.Java中的String为什么是不可变的?

2.既然不可变,那么replace()函数算不算改变了String呢?

首先看个例子:

String s = "hello";
System.out.println(s);
s = "java";
System.out.println(s);

输出为:

hello
java

我相信一部分同学肯定跟我一样,看到这有点懵了,这不是改变了吗?为什么还说String是不可变的呢?

原因在于例子中的s只是一个String对象的引用,并不是对象本身,当执行s = "java"时,就创建了一个新的String对象"java",而原来的"hello"还存在于内存中。

图示如下:

是不是到这有点理解了?那来看我们的第一个问题,为什么String对象是不可变的?

源头还是从String源码上进行分析,源码如下(jdk版本1.8):‘

public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
 
    //用于存储字符的字符数组,值不可更改
    private final char value[];
 
    //该字符串的hash code,默认值为0
    private int hash; // Default to 0

我们可以看到String其实就是一个被封装的char数组,并且这个数组被final修饰,值不可更改。

继续看我们的第二个问题。同样的方法,看一下replace()函数的源码

public String replace(char oldChar, char newChar) {  
    if (oldChar != newChar)   
    {  
        int len = value.length;//value就是一个数组,这里得到string字符串的长度  
        int i = -1;  
        char[] val = value; /* avoid getfield opcode */  
  
        while (++i < len)      //先确保字符串中有旧的字符  
        {  
            if (val[i] == oldChar)   
            {break;}  
        }  
  
        if (i < len)   
        {  
            char buf[] = new char[len];  
            for (int j = 0; j < i; j++)   
            {  
                buf[j] = val[j];  
            }  
            while (i < len) {  
                char c = val[i];  
                buf[i] = (c == oldChar) ? newChar : c;  
                i++;  
            }  
            return new String(buf, true); //!!! 
        }  
    }  
    return this;  
}  

注意三个!!!的位置,替换新的字符后,replace()内部返回一个新的String对象。String的其他方法也是一样的,都是在内部重新创建新的String对象,并且返回这个新的对象,原来的对象是不会改变的。

到这,上面提出的两个问题就大体上已经解决了。

下面再介绍下StringBuffer和StringBuilder两个类。参考:http://www.runoob.com/java/java-stringbuffer.html

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

上面的话简单的说就是:

String长度大小不可变;StringBuffer和StringBuilder长度可变。

StringBuffer线程安全,而StringBuilder线程不安全,但是StringBuilder速度快。

猜你喜欢

转载自blog.csdn.net/yong_zi/article/details/81296020