もくもくログ
主にIT 関連のメモをもくもくと綴っていきます
Java の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 インスタンスが生きているかどうかの判定ができて嬉しいです。