2011-08-12 17 views
5

私はfinalize()メソッドを持つ入れ子式のコンストラクタを持つスーパークラスを持っています。 super.finalizeを呼び出すのを忘れるサブクラスから保護するために、私はfinalizerガーディアン(EJ Item 7)を書いています。ここで Javaファイナライザーガーディアンが動作していないようですか?

public class Super { 

    public Super() {} 

    { 
     Object finalizerGuardian = new Object() { 
      @Override 
      protected void finalize() { 
       System.out.println("Finalizer guardian finalize"); 
       Super.this.finalize(); 
      } 
     }; 
    } 

    protected void finalize() { 
     System.out.println("Super finalize"); 
    } 

} 

はサンプルサブクラスである -
public class Sub extends Super { 

    public Sub() {} 

    protected void finalize() { 
     System.out.println("Sub finalize"); 
    } 

    public static void main(String[] args) 
      throws InterruptedException { 
     if (1 == 1) { 
      Sub s1 = new Sub(); 
     } 
     Runtime.getRuntime().gc(); 
     Thread.sleep(10000); 
    } 
} 

S1オブジェクトがスコープの外に出る

は、ファイナライザ保護者のファイナライズ()が呼び出されます、と私は、サブクラスのfinalizeメソッドからSYSOを取得し、スーパーのファイナライズから決して1つを得ることはありません。

私は混乱しています。基本的に何かを誤解していますか?

免責事項:ファイナライザは危険であり、推奨できないことなどを認識しています。ここでも問題を理解しようとしています。

答えて

8

あなたのケースでSuper.this.finalize();が実際にサブクラスからオーバーライドされたメソッドを呼び出すため効果的なJavaのファイナライザの保護者は、必要に応じてファイナライズロジック自体を実行する(例えば、実際のファイナライズを実行Superいくつかのメソッドを呼び出す)のではなくfinalize()メソッドを呼び出す必要があります。

public class Super { 
    private final Object finalizerGuardian = new Object() { 
      @Override 
      protected void finalize() { 
       Super.this.doFinalize(); 
      } 
    }; 

    private void doFinalize() { 
     System.out.println("Super finalize"); 
    } 
} 
+0

明白な問題を見るためには、「動作しません」ということに巻き込まれすぎています。ありがとう!! – Kal

2

あなたはSubSuper.finalize()方法をオーバーロードされます。

はまた、ファイナライザの保護者は、クラスのフィールドでなければならないことに注意してください。それが呼び出されていない理由です。

"finalizerGuardian"に電話するとSuper.this.finalize();と呼び出すと、実際にはSub.finalize()が呼び出されます。

2

他の人は既に動的ディスパッチがここで問題であると言いました。 finalizerGuardianは初期化ブロック内でのみ定義されています。これは、オブジェクトが初期化されるとすぐにオブジェクトがスコープから外れてGCされることを意味します。

あなたの最初の問題を解決しても(ファイナライゼーションを処理するクラスの最終メソッドを定義することによって)、finalizerGuardianをインスタンス変数に保存する必要があります。

2

Super.finalize()は、Subがそれをオーバーライドするため呼び出されません。 Super._finalize()メソッドを追加して、Super.finalize()とファイナライザーガーディアンから呼び出してみてください。

また、finalizerGuardianSuperのフィールドである必要があります。さもなければ、スーパーオブジェクトが依然として強く到達可能であっても、ガベージコレクションを得ることができます。

関連する問題