Send As SMS

プログラマメモ

プログラマのメモ、徒然、備忘録。 精進精進

2006/06/26

finalizeの実装(オーバライド)

個人的には、Object#finalize()は実装せずに、後始末が必要な処理は早い段階で明示的に後始末メソッドを作って行うようにしたほうがよいと思う。

この根拠は、
(1)
finalizeの呼び出しは、JVMに依存している。
(2)
finalizeの処理が時間かかる場合にアプリケーション全体の動作にたいする影響にたいしての危惧
(3)
super.finalize()の呼び出しにたいする注意が必要になる

finalizeの呼び出しに過渡なきたいをしたくないというのが本音。
プログラマができる後始末はちゃちゃとすませたほうが吉なのではないだろうか。
たしか、Syste.gc()の呼び出しはすすめられていなかったと思う。
※もとネタを探し中

といいつつも
ではどういったときにプログラマはfinalizeを実装したほうがよいのだろうか。
JNI(Java Native Interface)を利用したりして実メモリ操作に近い処理をしているような場合だろうか。

Javaのソースコードを簡単に調べてみた。
なんとなくパターンがある感じ。

(A)
java.awt.Font
で実装しているコードがあった。
これはあきらかにネイティブなものにたいする後始末パターン。
下記のような感じ。


/** ネイティブコール */
private native void pDispose();
/** overrideされている */
protected void finalize() throws Throwable {
if (this.peer != null) {
pDispose();
}
super.finalize();
}


(B)
java.awt.Window
これは、登録していたものから自分を削除するパターン(かな?)
で下記のような感じ。

protected void finalize() throws Throwable {
if (parent != null) {
((Window)parent).removeOwnedWindow(weakThis);
}
super.finalize();
}


(C)
javax.imageio.stream.ImageInputStreamImpl
これは、おそらくクローズしわすれ防止パターン。
下記のような感じのコード。

protected void finalize() throws Throwable {
if (!isClosed) {
try {
close();
} catch (IOException e) {}
}
super.finalize();
}


気がついたことがあるsuper.finalize()の呼び方が下のほうにある。

いまいちよくわかってないので、引き続き考えていきたい。

1 Comments:

H said...

finalize に関する話題提供します。

Effective Java には "Finalizer Guardian" というパターンが紹介されています。要は、

1. protected な finalize ではなく public なクリーンアップメソッド(InputStream.close() のような)を用意する。

2. private final なメンバを作成し、その中に protected finalize を作成するが、そこで 1 のクリーンアップメソッドを呼ぶ。

private final Object m_finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
cleanup();
}
};

継承利用するクラスユーザに finalize を強要せず、クリーンアップしわすれても Finalizer Guardian の finalize でなんとか対処できるようにできます。

7:40 午後  

コメントを投稿

Links to this post:

リンクを作成

<< Home