shion のアバター画像もくもくログページ一覧ブログ一覧技術メモ一覧ライセンス表記利用規約外部リンクconnpassGitHubSpeaker DeckTwitter[工事中]Shion のもくログバージョン1.2.5

もくもくログ

主にIT 関連のメモをもくもくと綴っていきます

この記事の情報は古い可能性があります
最終更新日:2019/09/01 07:40:25
【Java】WeakReference の挙動確認Java

Java のWeakReference がちゃんと動いているのか不思議だったので、サンプルを書いてみました。

WeakReference の挙動確認

Presenter のUI への参照がちゃんとnull になっているので、NullPointerException で落ちます。

実装例

import java.lang.ref.WeakReference;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 画面表示用
 */
class UI {
    private final Presenter mPresenter;

    public UI() {
        System.out.println("new UI");
        mPresenter = new Presenter(new WeakReference<>(this));
    }

    public void show() {
        System.out.println("show UI");
    }

    public void tap() {
        mPresenter.doAction();
    }


    @Override
    protected void finalize() throws Throwable {
        System.out.println("ui finalize() called!");
        super.finalize();
    }
}

/**
 * 処理実行用
 */
class Presenter {
    private final WeakReference<UI> mUiAccessor;

    public Presenter(WeakReference<UI> uiAccessor) {
        System.out.println("new Presenter");
        mUiAccessor = uiAccessor;
    }

    public void doAction() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("presenter's timer done!");
                System.out.printf("ui is null: %b\n", mUiAccessor.get() == null);
                mUiAccessor.get().show();
            }
        }, 3000);
        System.out.println("presenter set timer");
    }


    @Override
    protected void finalize() throws Throwable {
        System.out.println("presenter finalize() called!");
        super.finalize();
    }
}

/**
 * エントリポイント
 */
public class Main {
    public static void main(String[] args) {
        System.out.println("main() start!");

        UI ui = new UI();
        ui.tap();
        ui = null;
        System.gc();

        System.out.println("main() done!");
    }
}

実行結果

オンラインでJava コードを実行できるSoloLearn での実行結果です。

main() start!
new UI
new Presenter
presenter set timer
main() done!
ui finalize() called!
presenter's timer done!
ui is null: true

Exception in thread "Timer-0" java.lang.NullPointerException
    at Presenter$1.run(Presenter.java:24)
    at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
    at java.base/java.util.TimerThread.run(Timer.java:506)

何が嬉しいか

Android では、UI のライフサイクルの都合で、参照を持っているかどうかに関わらず、強制的にインスタンスが消えることがあります。
なので、弱参照として持っていると、UI インスタンスが生きているかどうかの判定ができて嬉しいです。

一覧に戻る