String:字符串常量池

一、設計思想

??為字符串開辟一個字符串常量池,創(chuàng)建字符串常量時,首先檢測字符串常量池是否存在該字符串。如存在該字符串對象,返回其引用;若不存在,實例化該字符串并放入常量池中,并返回其引用。

二、實現(xiàn)基礎

??(1)String類字符串實例化后的對象是不可變的,初始化是什么則這個對象就永遠是什么,相當于是常量,因此String的對象們可以維護成一個常量池。
??(2)運行時字符串常量池中有一個表,總是為池中所有的字符串對象維護一個引用,所以常量池中的這些字符串不會被GC回收。

三、操作常量池的情況

??凡是" "形式定義的字符串一定會操作常量池。
??不滿足上面的情況,但是被編譯成String str = " "形式的,會操縱常量池(從中取該常量,如果取不到,就創(chuàng)建一個)

??(1)直接賦值

String str = "Java";

??當"Java"字符串對象已經(jīng)存在于常量池中時,str直接指向常量池中的對象。如果不存在,在常量池中創(chuàng)建"Java",令str指向它。
??(2)運算符重載

String str = "Ja" + "va";

??Java中可以使用+進行兩個字符串的拼接。會被直接編譯成str = "Java",會操作常量池。事實上這句話在常量池中創(chuàng)建了3個對象:"Ja"、"va"、"Java"(如果常量池中原本沒有這些對象)。
??注意,如果是下面的情況:

String temp = "va";
String str = "Ja" + temp;

??或者:

String str = "Ja" + new String("va");

??此時str不會在編譯時不會被自動拼接,即不會被編譯成str = "Java"的形式,也就不會在常量池中創(chuàng)建"Java"的對象。但是還是會在常量池中創(chuàng)建"Ja"和"va"。

四、圖形化的例子

String m = "hello,world";
String n = "hello,world";
String u = new String(m);
String v = new String("hello,world");

1.會分配一個11長度的char[ ]對象['h','e','l','l','o',',','w','o','r','l','d'],并在常量池分配一個由這個char數(shù)組組成的字符串對象"hello,world",然后由m去引用這個字符串。
2.用n去引用常量池里邊的字符串"hello,world",所以和m引用的是同一個對象。
3.在堆中生成一個新的字符串,但內部的字符數(shù)組引用著m內部的字符數(shù)組??匆幌略创a就比較直觀了:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
/**
     * Initializes a newly created {@code String} object so that it represents
     * the same sequence of characters as the argument; in other words, the
     * newly created string is a copy of the argument string. Unless an
     * explicit copy of {@code original} is needed, use of this constructor is
     * unnecessary since Strings are immutable.
     *
     * @param  original
     *         A {@code String}
     */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

4.同樣會在堆中生成一個新的字符串,但內部的字符數(shù)組引用常量池里邊的字符串"hello,world"內部的字符數(shù)組,也就是m/n內部字符數(shù)組。

??使用圖來表示的話,情況就大概是這樣的(使用虛線只是表示兩者其實沒什么特別的關系):



??測試:

String m = "hello,world";
String n = "hello,world";
String u = new String(m);
String v = new String("hello,world");
            
System.out.println(m == n); //true 
System.out.println(m == u); //false
System.out.println(m == v); //false
System.out.println(u == v); //false 

五、String的equals()和intern()

??(1)在Java中用==判斷左右兩邊非基本數(shù)據(jù)類型的引用,是指判斷兩個引用是否是引用同一個對象。String的equals()方法則是判斷兩個字符串內部引用的字符數(shù)組對象的值是否相同(注意不要求是引用同一個數(shù)組對象)。源碼如下:

/**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
     *
     * @param  anObject
     *         The object to compare this {@code String} against
     *
     * @return  {@code true} if the given object represents a {@code String}
     *          equivalent to this string, {@code false} otherwise
     *
     * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

??(2)intern()方法:如果常量池中有與本字符串相同的(equals)字符串,就直接返回池中對象的引用,如果沒有就在常量池中創(chuàng)建該對象并返回其引用。源碼的注釋:

/**
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     */

??因此對兩個字符串使用intern()和==,也可以起到和equals()一樣的功能:

String m = new String("xixi");
String n = new String("xixi");
System.out.println(m.intern() == n.intern()); // true
System.out.println(m.equals(n)); // true
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 前言 最先接觸編程的知識是在大學里面,大學里面學了一些基礎的知識,c語言,java語言,單片機的匯編語言等;大學畢...
    oceanfive閱讀 3,395評論 0 7
  • 從網(wǎng)上復制的,看別人的比較全面,自己搬過來,方便以后查找。原鏈接:https://www.cnblogs.com/...
    lxtyp閱讀 1,436評論 0 9
  • 紫鵲界梯田 采芹人 他們說的我都不信 我只信你 在我眼前的模樣 山溪清澈似西施的眼眸 紅花艷艷似刑天共工留下的熱血...
    論語說文閱讀 566評論 0 2
  • 題目:在數(shù)組中的兩個數(shù)字如果前面一個數(shù)字大于后面的數(shù)字,則這兩個數(shù)字組成一個逆序對。輸入一個數(shù)組,求出這個數(shù)組中的...
    qmss閱讀 562評論 0 0
  • 下班后依然是照例在85度C買夜宵,左挑右選終究還是買了最常吃的海苔肉松和奶酥。其實在吃夜宵這件事上,深夜的朝暉路有...
    Whyya閱讀 495評論 0 1

友情鏈接更多精彩內容