String.intern的一點研究

開始之前先了解下常量池:https://blog.csdn.net/xdugucc/article/details/78193805

intern方法的解釋:

/**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * 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.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
    public native String intern();

這裏大概意思是intern用來返回常量池中的某字符串的引用,如果常量池中已經存在該字符串,則直接返回常量池中該對象的引用。否則,在常量池中加入該對象,然後 返回引用。值得注意的是下面的一段話,

* All literal strings and string-valued constant expressions are
* interned.
也就是說只對字符串值還有靜態的字符串的值表達式有值相同返回的引用就一定是相同的

直接來看一些測試例子來加深下理解

public class Main {
    public static String CONSTSTRING = "ef";
    public static void main(String[] args) {
      String a ;
      String b;
      String c;
      a = new String("a");//這裏看起來創建了兩個對象,常量池中"a",還有heap中String a;不過下面的b="a"在編譯期就在POOL創建了"a",所以只是創建了一個
      b = "a";
      pl(a==b);//false引用不同

      pl(a.intern()==b);//true;這裏a.intern()找到並給回了POOL中"a"的引用,所以true

      a = new String("1")+new String("1");
      b = "11";
      pl(a.intern()==b);//true; 據說jdk1.7之前false, jdk1.7之後true,筆者1.8;這裏可以看出是根據value來執行的
      a.intern();//值得注意intern不會改變對象的引用
      pl(a==b);//因此這裏是false

      /*
        值得注意intern中的
        * All literal strings and string-valued constant expressions are
        * interned.
        也就是說只對字符串值還有靜態的字符串的值表達式,不能有引用
       */
      a="a"+"b";
      b="ab";
      pl(a==b);//true

      String temp = new String("aa");
      a="a"+temp;
      b="aaa";
      pl(a.equals(b));//true;
      pl(a.intern()==b);//false,因爲temp是對象的引用,即使是滿足a.equal(b)==true

      c="bc";
      a="a"+c;
      b="abc";
      pl(a == b);//false 同樣的這樣也不行

        a="ef";
        pl(a==CONSTSTRING);//字符串常量滿足

      a="cd"+CONSTSTRING;
      b="cdef";
      pl(a==b);//false;CONSTSTRING也是引用
    }

    public final static void pl(Object object){
        System.out.println(object);
    }

}

參考自https://www.cnblogs.com/Kidezyq/p/8040338.html

其中有些地方筆者認爲有誤,但是要詳細的多,可能是程度不夠吧

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章