Effective Javaを読んでいる⑦

ファイナライザだめ

System.runFinalizersOnExitと、Runtime.System.runFinalizersOnExitは悪魔の双子

ファイナライザが実行中にキャッチされない例外がスローされると例外が無視されてファイナライズが終了する

public class Test {
    public static void main(String[] args){
        
        for(int i = 0; i < 1000000; i++){
            new Akihiro();
        }
    }
}


class Akihiro {
    @Override
    public void finalize(){//ただひたすらに"start"だけ出力される
        System.out.println("start");
        int i = 3/0;
        System.out.println("end");
    }
}
 

ファイナライザはパフォーマンス的にもダメ

じゃあどうするの?

→明示的な終了メソッドを書く

  1.  privateなstateを表すフィールドを持っておいて終了メソッドが呼ばれたらstateを終了に

  2. stateが終了の状態でなんかメソッドが呼ばれたらIllegalStateExceptionを投げる

終了メソッドの呼び出しはtry { ~~ } finally { ここでする }

そもそもなんであるの?

  • セーフティネットとしての使用  closeの呼び忘れとか
  • native peer云々はよくわからん(Javaの世界の外で確保されたリソースはGCに開放されないみたいな話?)

finalizeを実装する場合は実装クラスの親のfinalizeを明示的に呼び出す必要がある(親のfinalizeは勝手に呼び出されない)

 →忘れちゃう

  →finalizer guardian

public class Foo {
  private final Object finalizerGuardian = new Object(){
    protected void finalize() throws Throwable {
        //Fooのためのファイナライザを
    }
  }
}

こうしとくとFooを継承したClassがfinalizeをオーバーライドした時に親クラスのfinalizeを呼び出してなくてもfinalizerGuardianインスタンスのfinalizeが呼び出されるのでfinalizeできる。

enclosing classってなんだ

What is Enclosing class in Java? - Quora インナークラスに焦点を当てた場合の、インナークラスを持ってるクラスのこと