好奇心から、
finalize()
メソッドのアクセス修飾子がprotected
として作成されるのはなぜですか。なぜpublic
できないのですか?誰かが私にこれの背後にある特定の理由を説明できますか?
また、finalize()
メソッドは一度しか呼び出されないことを知りました。私のプログラムで内部的にそれを2回呼び出した場合、何が起こっていますか?ガベージコレクターは再びこれを呼び出しますか?
private void dummyCall() {
try {
finalize();
finalize();
} catch (Throwable e) {
e.printStackTrace();//NOT REACHES EXCEPTION
}
}
私は別の質問であなたの質問に答えます:
finalize
メソッドを保護すべきではないのはなぜですか?
一般に、物事はできるだけプライベートに保つようにしてください。それがカプセル化のすべてです。それ以外の場合は、すべてpublic
を作成できます。 finalize
をprivate
にすることはできません(派生クラスがそれにアクセスしてオーバーライドできるようにする必要があるため)少なくともprotected
にする必要がありますが、それが望ましくないときにより多くのアクセス?
あなたのコメントをもっと注意深く読んだ後、私は今あなたの要点を理解していると思います。すべてがJava.lang.Object
から派生し、その結果protected
メンバーにアクセスするため、それ(またはJava.lang.Object
のメソッド)には何の違いもないため、 public
ではなくprotected
になります。個人的には、これをJavaの設計上の欠陥として数えます。これは確かにC#で修正されています。問題は、finalize
が保護されている理由ではありません。それで大丈夫です。実際の問題は、基本クラス型のオブジェクト参照を介して基本クラスの保護されたメソッドを呼び出せないようにする必要があることです。 Eric Lippertが ブログエントリ 保護されたメンバーにそのような種類のアクセスを許可することが悪い考えである理由について議論しています この質問でスタックオーバーフローについてさらに詳しく説明します 。
Finalize()メソッドのアクセス修飾子が保護されているのはなぜですか。なぜ公開できないのですか?
これは、JVM以外から呼び出されるべきではないため、パブリックではありません。ただし、その動作を定義する必要があるサブクラスによってオーバーライドできるように、保護する必要があります。
私のプログラムでそれを2回呼び出した場合、内部的に何が起こっていますか?
あなたはそれをあなたが望むすべてのものと呼ぶことができ、結局のところそれは単なるメソッドです。ただし、public static void main(String [] args)
と同様に、JVMにとって特別な意味があります。
ガベージコレクターは再びこれを呼び出しますか?
はい
Finalize()に反対する
上記のステートメントのエラーに注意してください、私は少し疲れています:-)
それを議論する このリンク をチェックしてください。
基本的には、JVM(ガベージコレクター)によってのみ呼び出されるため、private
であることが最も理にかなっています。しかし、サブクラスがfinalize()
の一部として親finalize()
メソッドを呼び出すことができるようにするには、protected
である必要があります。
(Edit-そして一般的な注意-finalize()メソッドの使用は、呼び出されることを保証する方法がないため、通常はお勧めしません。それはあなたがそれを使う機会がないことを意味するわけではありませんが、それはまれです。)
finalize()
が1回だけ呼び出される部分は、GCからの呼び出しにのみ適用されます。オブジェクトに非表示のフラグ「finalize()
がGCによって呼び出されました」があり、GCがそのフラグをチェックしてオブジェクトの処理方法を知っていると想像できます。フラグは、finalize()
への独自の手作りの呼び出しによる影響を受けません。
ファイナライズについては、ハンスベーム(ガベージコレクションに関する彼の研究で有名)の この記事 をお読みください。これはファイナライズに関する目を見張るものです。特に、Boehmは、ファイナライズが必然的に非同期である理由を説明しています。当然ですが、ファイナライズは強力なツールですが、特定の仕事に適したツールとなることはほとんどありません。
これはpublic
(またはデフォルトのアクセス)ではありません。オブジェクトがガベージコレクションされたときに内部的にJVMによって呼び出されることを意図しているためですnotは他のものによって呼び出されることを意味します。そして、それはprivate
ではありません。これは、オーバーライドされることを意図しており、プライベートメソッドをオーバーライドできないためです。
私のプログラムでそれを2回呼び出した場合、内部的に何が起こっていますか?ガベージコレクターはこれを再度呼び出しますか?
おそらくそうですが、これが何らかの意味をなすシナリオを想像するのは困難です。finalize()
のポイントは、オブジェクトがガベージコレクションされたときにクリーンアップを行うことです。そして、それでもうまくいかないので、実際に実験するのではなく、完全に回避する必要があります。
finalize()は、オブジェクトが収集されたときにリソースをクリーンアップするためにJVMによってのみ使用されます。クラスがコレクションに対して実行する必要があるアクションを定義することは合理的であり、そのためにsuper.finalize()にアクセスする必要があります。外部プロセスがオブジェクトを収集するタイミングを制御できないため、外部プロセスがfinalize()を呼び出すことは実際には意味がありません。
また、finalize()メソッドは一度しか呼び出されないことを知りました。私のプログラムでそれを2回呼び出した場合、内部的に何が起こっていますか?
あなたはおそらくこれをC++〜デストラクタの印象の下で尋ねます。 Java finalize()メソッドでは、メモリのクリアなどのマジックは行われません。ガベージコレクタによって呼び出されることになっています。ただし、その逆はありません。
Joshua Blochの「Effective Java」の対応する章を読むことをお勧めします。ファイナライザを使用することは悪い習慣であり、パフォーマンスやその他の問題を引き起こす可能性があると述べており、それらを使用する必要があるのはいくつかの場合のみです。この章は次の言葉で始まります。
ファイナライザは予測不可能で、多くの場合危険であり、一般に不要です。
finalize
が保護されている理由は、JDKの一部のクラスによってオーバーライドされ、それらのオーバーライドされたメソッドがJVMによって呼び出されたためだと思います。