String詳解

String詳解:java

(1)String不屬於基本數據類型,Stirng是一個對象
(2)String類被final修飾,不能夠被
(3)String能夠經過「+「鏈接
(4)String類的本質是char[]
(5)String運行時維護常量池

類的定義及主要屬性

(1)類的定義:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
(2)主要屬性(GDK1.6):
private final char value[];  //String本質就是Char數組
private final int offset;   //偏移位
private final int count;  //就是Sting的length
private int hash;  //hash碼

final簡析

簡單的理解:
    若變量是基本類型則值不變
    若變量是引用類型則引用不變   
String內部變量是被Final修飾的,對String的改變不能將原來的String改變,只能從新返回一個新的String。這是String與其餘普通對象的重要區別。

 經過源碼理解"對String的改變不能將原來的String改變,只能從新返回一個新的String"這句話。數組

public String(char value[], int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count <= 0) {
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= value.length) {
            this.value = "".value;
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}

public static char[] copyOfRange(char[] original, int from, int to) {
    int newLength = to - from;
    if (newLength < 0)
        throw new IllegalArgumentException(from + " > " + to);
    char[] copy = new char[newLength];//建立新的數組對象
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}

replace方法咱們會誤覺得會發生值的改變,以下this

String str = 「123」, str = str.replace('1','a'), 咱們會誤認爲a的值發生改變,查看源碼發現其實建立了一個新對象,而後讓str指向這個對象。spa

//源碼
public String replace(char oldChar, char newChar) {
    if (oldChar != newChar) {
        int len = value.length;
        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;
}

字符串的建立

(1)new建立 String str = new String(「123「);
此方式必定會在堆區建立一個新對象,使用String類的intern()方法能夠將其放入常量池。
(ps:java不要求常量必定在編譯期才能產生)
(2)直接指定 String str = 「123」;
對象建立時先查看常量池,常量池中存在就不建立,不存在時建立新對象而且放入常量池。
(3)使用「+」 String str = 「12」 + 「3」;
使用直接指定或者使用純字符串來建立時,先檢查常量池。若是存在則不建立,不存在時建立新對象而且放入常量池。
(4) String str2 = "12";
    String str7 = str2 + "1";
    使用包含變量的表達式來建立時不檢查常量池。

字符串的建立例子

public class StringTest {
    public static void main(String[] args) {
        //new建立
        String str1 = new String("123");
        //直接指定
        String str2 = "123";
        System.out.println(str1 == str2);//false
        //使用 "+"
        String str3 = "12" + "3";
        System.out.println(str2 == str3);//true
        //使用包含變量的表達式來建立
        String str4 = new String("12");
        String str5 = str4 + "3";
        System.out.println(str5 == str2);//false
        //使用包含變量的表達式來建立
        String str6 = "12";
        String str7 = "3";
        String str8 = str6 + str7;
        System.out.println(str8 == str2);//false

    }
}

改變Stirng對象

String對象真的是不可變的嗎?其實咱們能夠使用反射機制改變,例子以下:code

public class StringReflection {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        String str = "123";
        System.out.println(str); //123

        Field valueFiled = String.class.getDeclaredField("value");
        //訪問屬性設置
        valueFiled.setAccessible(true);
        char[] oldValue = (char[]) valueFiled.get(str);
        oldValue[0] = 'A';
        System.out.println(str);  //A123
    }
}
相關文章
相關標籤/搜索