6 行目の変数 t2 は、オブジェクトへの唯一の参照ではありません。関数 go で作成されたオブジェクト t2 への t からの参照があり、関数 go によって返されたのと同じオブジェクトである t1 への参照を保持します。したがって、6 行目は参照の数を減らすだけですが、オブジェクトへのライブ参照はまだ存在します。
編集: より詳細な説明を試してみましょう。まず、説明を簡単にするためにコードを少し作り直しました。1 行に 1 つのステートメントと混乱の少ない変数名 + 3 つの関連オブジェクトを A、B、C の文字で識別しました。
1. public class Tahiti {
2. Tahiti u;
3. public static void main(String[] args) {
4. Tahiti t = new Tahiti(); // object A
5. Tahiti t2 = t.go(t);
6. t2 = null;
7. // more code here
8. }
9. Tahiti go(Tahiti s) {
10. Tahiti s1 = new Tahiti(); // object B
11. Tahiti s2 = new Tahiti(); // object C
12. s1.u = s2;
13. s2.u = s1;
14. s.u = s2;
15. return s1;
16. }
17. }
4 行目: 変数 t は、新しいオブジェクトを参照するように初期化されます。そのオブジェクト自体を A と呼びましょう (Java では通常名前はありませんが、この説明のために名前を付けた方が簡単です)。
5 行目: t が関数 go に渡されるので、9 行目に進みます。
9 行目: パラメータ s は、4 行目で作成されたオブジェクト A を参照します。
10 行目: オブジェクト B を指すように変数 s1 を初期化します。
11行目:オブジェクトCを参照するように変数s2を初期化
12 行目: s1.u は s2 を参照するように設定されています。これは、オブジェクト B が C への参照を取得することを意味します。
13 行目: s2.u は s1 を参照するように設定されているため、オブジェクト C は B への参照を取得します。
14 行目: su は s2 を参照するように設定されています。これは、オブジェクト A が C への参照を取得することを意味します。C も B への参照を持っているため、この時点で A から B へのチェーンが存在することに注意してください。
15 行目 オブジェクト B を返し、5 行目に戻る
5 行目: t2 はオブジェクト B を参照するように設定されます (B は、t2 によって直接 1 回、および t が B を参照する C を参照するオブジェクト A を参照するため、2 回参照されるようになりました)
6 行目: 参照 t2 が null に設定されているため、B は 1 つの参照を失いますが、A が参照するポイント C が B を参照する t はまだ有効です