String=「」とnew String(「」)の違い


生産の問題を探しているときに、WeakReferenceの問題に遭遇しました.
テストコード
public static void testWeakReference() throws Exception {
        String s = "1";

        ReferenceQueue q = new ReferenceQueue();
        WeakReference w = new WeakReference(s, q);
        System.out.println("w.get():" + w.get());
        s = null;
        System.gc();
        System.out.println("s:" + s);
        System.out.println("w.get():" + w.get());
        System.out.println("w.isEnqueued():" + w.isEnqueued());
    }

結果:
w.get():1
s:null
w.get():1---gc後に収集されていない
w.isEnqueued():false
テストコード
public static void testWeakReference() throws Exception {
        String s = new String("1");

        ReferenceQueue q = new ReferenceQueue();
        WeakReference w = new WeakReference(s, q);
        System.out.println("w.get():" + w.get());
        s = null;
        System.gc();
        System.out.println("s:" + s);
        System.out.println("w.get():" + w.get());
        System.out.println("w.isEnqueued():" + w.isEnqueued());
    }

結果:
w.get():1
s:null
w.get():null---gc後に収集
w.isEnqueued():true
なぜString s=new String(「1」);とString s="1";異なる結果をもたらしますか?
理由:両方の文はStringオブジェクトの参照を返しますが、jvmの処理方法は異なります.1つ目の場合、jvmはすぐにheapにStringオブジェクトを作成し、そのオブジェクトの参照をユーザーに返します.2つ目の場合、jvmはまず、内部メンテナンスstrings poolでStringのequelsメソッドを使用して、オブジェクトプールにStringオブジェクトが格納されているかどうかを検索します.ある場合は、heapで新しいStringオブジェクトを再作成することなく、既存のStringオブジェクトをユーザーに返します.オブジェクトプールにStringオブジェクトがない場合、jvmはheapに新しいStringオブジェクトを作成し、strings poolに参照を追加しながらユーザーに参照を返します.注意:最初の方法でオブジェクトを作成する場合、jvmはプログラムがStringのinternメソッドを呼び出さない限り、strings poolにオブジェクトを自動的に配置しません.
さらにinternメソッドはstrings poolに明示的に配置することを指定します.
String str1 = new String("abc");//jvmスタック上にStringオブジェクトstr 1=str 1を作成する.intern();//プログラムはstrings poolにstr 1を明示的に配置し、intern実行プロセスは、strings pool//abcオブジェクトの参照があるかどうかを確認し、ない場合は、スタックにオブジェクトを新規作成し、新しいオブジェクトの参照を//strings poolに追加します.この文を実行すると、str 1が本来指すStringオブジェクトはすでにゴミオブジェクトとなり、いつでも//GCに収集されます.
参照先:http://blog.csdn.net/kenwug/article/details/1606873