1. 程式人生 > >String.intern的一點研究

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

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