Finalize メソッド、クローズ可能なインターフェース、および try-with-resources ステートメント (Java 7) - 1

「こんにちは、アミーゴ!」

「 finalize () メソッドについてあなたと話し合うことにしました。」

「覚えていると思いますが、finalize() は、ガベージ コレクターがオブジェクトを破棄する前にオブジェクトによって呼び出される特別なメソッドです。」

「このメソッドの主な目的は、ファイルや I/O ストリームなどを閉じることによって、使用されている外部の非 Java リソースを解放することです。」

「残念ながら、このメソッドは私たちの期待に応えません。Java 仮想マシンは、オブジェクトの破棄や、finalize メソッドの呼び出しを、必要に応じて延期できます。さらに、このメソッドが確実に実行されるという保証もありません」まったく呼び出されません。呼び出されない状況はたくさんありますが、すべて「最適化」の名の下に行われます。

「参考資料が 2 つあります。」

Joshua Bloch は、こ​​の方法について優れた記事を書いています:リンク
短い抜粋を言い換えます:

  1. Finalize() は次の 2 つの場合にのみ使用できます。
    1. ロギングによるリソースの検証またはクリーンアップ用。
    2. リソース リークにとって重要ではないネイティブ コードを操作する場合。
  2. Finalize() により、オブジェクトのクリーンアップ時に GC が 430 倍遅くなります
  3. Finalize() が呼び出されない可能性があります
インタビューで、ファイナライズは有害で危険な松葉杖であり、その存在自体が混乱を招くと私が言ったら、私は正しいでしょうか?

「まあ、それで今日は楽しかったです、エリー。」

「Java 7 には、 finalizeメソッドを置き換える新しいステートメントがあります。これはtry-with-resourcesと呼ばれます。これは実際にはFinalizeの代替ではなく、むしろ代替アプローチです。」

「トライキャッチのようなものですが、リソースは必要ですか?」

「これはtry-catchにほぼ似ています。finalize () メソッドとは異なり、try-catch-finally ステートメント内のfinally ブロックが常に実行されるということですプログラマーは、リソース解放する必要がある場合にもこのテクニックを使用しました。スレッドを閉じるなど。
 「例を示します。」

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read(…);
}
finally
{
 if (is != null)
 is.close();
}

「 tryブロックが適切に実行されたか、例外が発生したかに関係なく、 finallyブロックは常に呼び出され、そこで占有されたリソースを解放することができます。」

「そこで、Java 7 では、このアプローチを公式にすることが次のように決定されました。」

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read(…);
}

「この特別なtryステートメントはtry-with-resourcesと呼ばれます(コレクションにforeach呼ばれる代替ステートメントがあるのと似ています)。」

"try の後に、変数が宣言され、オブジェクトが作成される括弧があることに注意してください。これらのオブジェクトは、中括弧で示された try ブロック内で使用できます。try ブロックの実行が完了すると、正常に終了したかどうかに関係なく、は例外でした。括弧内で作成されたオブジェクトに対して close() メソッドが呼び出されます。」

「面白いですね。この表記は前の表記よりもはるかにコンパクトです。まだ理解できているかどうかわかりません。」

「あなたが思っているほど難しくありません。」

「それでは、各オブジェクトのクラスを括弧内に指定できますか?」

「はい、もちろん、そうでなければ括弧はほとんど役に立ちません。」

「そして、try ブロックを終了した後に別のメソッドを呼び出す必要がある場合、それをどこに配置すればよいでしょうか?」

「ここでのことはもう少し微妙です。Java 7 では次のインターフェイスが導入されています。」

public interface AutoCloseable
{
 void close() throws Exception;
}

「クラスはこのインターフェイスを実装できます。そして、try-with-resources ステートメント内でそのオブジェクトを使用できます。«自動クロージャ» の try-with-resources ステートメントのかっこ内に作成できるのは、そのようなオブジェクトのみです。」

「言い換えれば、close メソッドをオーバーライドして、オブジェクトを「クリーンアップ」するコードを記述する必要があるのに、別のメソッドを指定することはできないということですか?

「はい。ただし、複数のオブジェクトを指定できます。セミコロンで区切るだけです。」

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read(…);
 os.write(…);
}

「それは良いことですが、私が期待していたほどクールではありませんでした。」

「それほど悪くはありません。時間が経てば慣れるでしょう。」