Java : Reference (参照) - API使用例

Reference (Java SE 16 & JDK 16)の使用例まとめです。
だいたいのメソッドを網羅済みです。
公式API仕様のおともにどうぞ。


概要

クラス構成

Referenceは、(弱)参照オブジェクトのベースとなるクラスです。

Java 16 の時点では、

  • ソフト参照 (SoftReference)
  • 弱参照 (WeakReference)
  • ファントム参照 (PhantomReference)

が提供されています。

一番よく使われるのは、WeakReferenceでしょうか。
とはいえ、あまり Reference に頼る設計にはしないほうがよいと、個人的には思います。
(GC に依存した挙動となり、テストもしづらいため)

// 弱参照(WeakReference)の使用例です。

var sb = new StringBuilder("abcd");
final Reference<StringBuilder> ref = new WeakReference<>(sb);

System.out.println(ref.get()); // abcd

// 変数 sb による強参照が残っている状態です。
System.gc();
System.out.println(ref.get()); // abcd

// 変数 sb の強参照をクリアします。
sb = null;
System.out.println(ref.get()); // abcd

// その状態で、GCを要求します。
System.gc();
System.out.println(ref.get()); // null

補足

  • 本記事のコード例では、GCを実行するために System.gc メソッドを使っています。
  • しかし、一般的なJavaプログラムでは、System.gc を直接呼び出すことはあまりおすすめしません。
    Javaシステムが自分自身の最適なタイミングでGCを実行してくれるためです。

メソッド

void clear ()

この参照オブジェクトをクリアします。

var sb = new StringBuilder("abcd");
final Reference<StringBuilder> ref = new WeakReference<>(sb);

System.out.println(ref.get()); // abcd

ref.clear();
System.out.println(ref.get()); // null
var sb = new StringBuilder("abcd");

final var queue = new ReferenceQueue<StringBuilder>();
final Reference<StringBuilder> ref = new WeakReference<>(sb, queue);

System.out.println(ref.get()); // abcd

ref.clear();
System.out.println(ref.get()); // null

// キューには入りません。
System.out.println(queue.poll()); // null

protected Object clone ()

CloneNotSupportedExceptionをスローします。

常に CloneNotSupportedException が発生します。
よって、Reference を clone するべきではありません。

var sb = new StringBuilder("abcd");
final var ref = new WeakReference<StringBuilder>(sb) {

    public void test() {
        try {
            clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("CloneNotSupportedException発生!");
        }
    }
};

ref.test();

// 結果
// ↓
//CloneNotSupportedException発生!

boolean enqueue ()

この参照オブジェクトをクリアし、それが登録されているキューに登録オブジェクトを追加します。

var sb = new StringBuilder("abcd");

final var queue = new ReferenceQueue<StringBuilder>();
final Reference<StringBuilder> ref = new WeakReference<>(sb, queue);

System.out.println(ref.get()); // abcd

final var ret = ref.enqueue();
System.out.println(ret); // true
System.out.println(ref.get()); // null
System.out.println(queue.poll()); // java.lang.ref.WeakReference@7625b376
var sb = new StringBuilder("abcd");
final Reference<StringBuilder> ref = new WeakReference<>(sb);

System.out.println(ref.get()); // abcd

final var ret = ref.enqueue();
System.out.println(ret); // false
System.out.println(ref.get()); // null

T get ()

参照オブジェクトのリファレントを返します。

var sb = new StringBuilder("abcd");
final Reference<StringBuilder> ref = new WeakReference<>(sb);

System.out.println(ref.get()); // abcd

sb = null;
System.out.println(ref.get()); // abcd

System.gc();
System.out.println(ref.get()); // null

boolean isEnqueued ()

非推奨。 このメソッドは当初、参照オブジェクトがクリアされてエンキューされたかどうかをテストするために指定されていましたが、このテストを行うために実装されたことはありません。

非推奨です。

static void reachabilityFence (Object ref)

指定された参照によって参照されるオブジェクトが、オブジェクトが到達不能になる可能性のあるプログラムの以前のアクションに関係なく、「強く到達可能な」のままであることを保証します。このため、参照されたオブジェクトは、少なくともこのメソッドが呼び出されるまでガベージ・コレクションによって再要求できません。

まだ動作を確認しきれていないため、コード例も準備できていません。
(いずれ更新するかもしれません…)

boolean refersTo (T obj)

この参照オブジェクトの参照がobjかどうかをテストします。

var sb1 = new StringBuilder("abcd");
final Reference<StringBuilder> ref = new WeakReference<>(sb1);

System.out.println(ref.refersTo(sb1)); // true

var sb2 = new StringBuilder("XYZ");

System.out.println(ref.refersTo(sb2)); // false

関連記事

ページの先頭へ