36

好奇心から、

finalize()メソッドのアクセス修飾子がとして作成されるのはなぜですかprotected。なぜできないのpublicですか?誰かが私にこれの背後にある特定の理由を説明できますか?

finalize()また、メソッドが一度だけ呼び出されることを知りました。プログラム内で2回呼び出すと、どうなりますか?ガベージコレクターはこれを再度呼び出しますか?

private void dummyCall() {
    try {
        finalize();
        finalize();
    } catch (Throwable e) {
        e.printStackTrace();//NOT REACHES EXCEPTION
    }
}
4

9 に答える 9

26

私はあなたの質問に別の質問で答えます:

なぜfinalizeメソッドを保護すべきではないのですか?

一般的に、あなたは物事をできるだけプライベートに保つように努めるべきです。それがカプセル化のすべてです。そうでなければ、あなたはすべて publicを作ることができます。finalizeできませんprivate(派生クラスはそれをオーバーライドできるようにアクセスできる必要があるため)、少なくともそうする必要がありますprotectedが、望ましくない場合にアクセスを増やすのはなぜですか?


あなたのコメントをもっと注意深く読んだ後、私はあなたの要点を今理解していると思います。あなたのポイントは、すべてがそのメンバーから派生しjava.lang.Object、その結果としてそのメンバーにアクセスするため、とは対照的に、それ(またはそのことに関するprotected方法)に違いはないということだと思います。個人的には、これをJavaの設計上の欠陥と見なします。これは確かにC#で修正されています。問題は、なぜ保護されているのかではありません。それで大丈夫です。本当の問題は、基本クラスタイプのオブジェクト参照を介して基本クラスの保護されたメソッドを呼び出すことができないようにする必要があるということです。Eric Lippertは、保護されたメンバーへのそのような種類のアクセスを許可することがなぜ悪い考えであるかを議論するブログエントリを持っています。これは、この質問のStackOverflowでさらに詳しく説明されていますjava.lang.Objectpublicprotectedfinalize

于 2010-02-18T19:17:07.177 に答える
23

finalize() メソッドのアクセス修飾子が保護されているのはなぜですか。なんで公にできないの?

JVM 以外から呼び出されるべきではないため、パブリックではありません。ただし、動作を定義する必要があるサブクラスによってオーバーライドできるように、保護する必要があります。

プログラムで2回呼び出すと、内部的に何が起こっていますか?

好きなように呼び出すことができます。結局のところ、それは単なるメソッドです。ただし、 と同様public static void main(String [] args)に、JVM にとって特別な意味があります。

ガベージ コレクターはこれを再度呼び出しますか?

はい

于 2010-02-18T19:19:12.583 に答える
12
  • finalize は gc によってのみ呼び出されることを意図しているため、パブリック アクセスは必要ありません。
  • finalize はgc によって1 回だけ呼び出されることが保証されています。自分で呼び出すと、gc が認識しないため、この保証が破られます。
  • オーバーライド クラスはファイナライズをパブリックにすることができますが、これは上記の理由から悪いと思います。
  • ファイナライズによってスローされた例外は、gc のファイナライザー スレッドを強制終了する可能性があるため、ファイナライズには多くのコードを含めないでください。

finalize() に対する暴言

  • ネイティブ リソースや、dispose() または close() の呼び出しが必要なリソースを管理すると、jvm がメモリ不足になった場合にのみ解放されるため、見つけにくいバグが発生する可能性があります。リソースを手動で解放する必要があります。Finalize は、リソース リークのデバッグや、リソースを手動で管理するのが面倒な場合にのみ使用してください。
  • finalize は gc の追加スレッドで呼び出され、リソースのロックなどの問題を引き起こす可能性があります。
  • WeakReference や ReferenceQueue などの参照クラスは、クリーンアップを処理する代替の (かなり複雑な) 方法であり、ネイティブ リソースの finalize() と同じ問題が発生する可能性があります。

上記のステートメントのエラーに注意してください。私は少し疲れています:-)

于 2010-02-18T20:04:26.310 に答える
3

一度だけ呼び出されるという部分finalize()は、GCからの呼び出しにのみ適用されます。finalize()オブジェクトが「GCによって呼び出された」非表示のフラグを持ち、GCがそのフラグをチェックしてオブジェクトをどう処理するかを知っていると想像できます。フラグは、への独自の手作りの呼び出しによって影響を受けることはありませんfinalize()

ファイナライズについては、ハンスベーム(ガベージコレクションの研究で有名)のこの記事を読んでください。これは、ファイナライズについての目を見張るものです。特に、ベームは、ファイナライズが必然的に非同期である理由を説明しています。当然の結果として、ファイナライズは強力なツールですが、特定のジョブに適したツールになることはめったにありません。

于 2010-02-18T21:00:19.827 に答える
3

それについて説明しているこのリンクをチェックしてください。

private基本的には、JVM (ガベージ コレクター) によってのみ呼び出される必要があるため、 であることが最も理にかなっています。しかし、サブクラスが親finalize()メソッドをその一部として呼び出せるようfinalize()にするには、それはprotected.

(編集- そして一般的な注意事項 - finalize() メソッドの使用は、それが呼び出されることを保証する方法がないため、一般的に推奨されていません。珍しいだけです。)

于 2010-02-18T19:18:53.350 に答える
2

publicオブジェクトがガベージコレクションされるときにJVMによって内部的に呼び出されることを意図しているため、そうではありません(またはデフォルトアクセス)-他のものによって呼び出されることを意図していません。privateオーバーライドすることを意図しており、プライベート メソッドをオーバーライドできないからではありません。

プログラムで2回呼び出すと、内部的に何が起こっていますか? ガベージ コレクターはこれを再度呼び出すでしょうか。

おそらくそうですが、これが何らかの意味を成すシナリオを想像するのは難しいです。ポイントはfinalize()、オブジェクトがガベージコレクションされたときにクリーンアップを行うことです。そして、それはうまくいかないので、実験するのではなく、完全に避けるべきものです.

于 2010-02-18T19:21:14.193 に答える
1

保護されている理由finalizeは、おそらくJDKの一部のクラスによってオーバーライドされ、それらのオーバーライドされたメソッドがJVMによって呼び出されるためだと思います。

于 2012-05-06T11:19:25.903 に答える
1

finalize() は、オブジェクトが収集されたときにリソースをクリーンアップするために JVM によってのみ使用されます。クラスがコレクションに対して実行する必要があるアクションを定義することは合理的であり、そのためには super.finalize() にアクセスする必要がある場合があります。外部プロセスはオブジェクトがいつ収集されるかを制御できないため、外部プロセスが finalize() を呼び出すことは実際には意味がありません。

于 2010-02-18T19:21:35.797 に答える
1

また、finalize() メソッドは 1 回しか呼び出されないことがわかりました。プログラムで2回呼び出すと、内部的に何が起こっていますか?

C++ の ~destructors の印象の下でおそらくこれを尋ねます。Java finalize () メソッドでは、魔法のようなことはしません (メモリのクリアなど)。ガベージコレクターによって呼び出されるはずです。しかし、その逆ではありません。

Joshua Bloch の「Effective Java」の特派員の章を読むことをお勧めします。ファイナライザーの使用は悪い習慣であり、パフォーマンスやその他の問題を引き起こす可能性があり、使用する必要がある場合はいくつかあると述べています. この章は次の言葉で始まります。

ファイナライザは予測不可能で、危険であることが多く、一般的に不要です。

于 2010-02-18T19:23:53.353 に答える