広告

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

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


概要

参照オブジェクトための抽象基底クラスです。 このクラスは、すべての参照オブジェクトに対して共通のオペレーションを定義します。 参照オブジェクトはガベージ・コレクタと密接に連携して実装されるので、このクラスを直接サブクラス化することはできません。

クラス構成

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

Java 18 の時点では、

が提供されています。

一番よく使われるのは、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 ()

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

final 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
final 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 するべきではありません。

final 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 ()

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

final 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
final 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)

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

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

final 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

関連記事

ページの先頭へ