Die finalize-Methode, die schließbare Schnittstelle und die try-with-resources-Anweisung (Java 7) – 1

„Hallo, Amigo!“

„Ich habe gerade beschlossen, die finalize ()-Methode mit Ihnen zu besprechen .“

„Wenn Sie sich erinnern, ist finalize() eine spezielle Methode, die von einem Objekt aufgerufen wird, bevor der Garbage Collector es zerstört.“

„Der Hauptzweck dieser Methode besteht darin, genutzte externe Nicht-Java-Ressourcen durch das Schließen von Dateien, E/A-Streams usw. freizugeben.“

„Leider entspricht diese Methode nicht unseren Erwartungen. Die Java Virtual Machine kann die Zerstörung eines Objekts sowie den Aufruf der Finalize-Methode so lange hinauszögern, wie sie möchte. Darüber hinaus kann nicht garantiert werden, dass diese Methode dies auch tut.“ überhaupt aufgerufen. Es gibt viele Situationen, in denen es nicht aufgerufen wird, alles im Namen der „Optimierung“.

„Ich habe zwei Referenzen für Sie:“

Joshua Bloch hat einen guten Artikel über diese Methode geschrieben: Link
Ich paraphrasiere einen kurzen Auszug:

  1. finalize() kann nur in zwei Fällen verwendet werden:
    1. Zur Überprüfung oder Bereinigung von Ressourcen mit Protokollierung.
    2. Bei der Arbeit mit nativem Code ist dies nicht kritisch für Ressourcenlecks.
  2. finalize() macht den GC beim Bereinigen von Objekten 430-mal langsamer
  3. finalize() wird möglicherweise nicht aufgerufen
Wenn ich in einem Interview sage, dass Finalize eine schädliche und gefährliche Krücke ist, deren bloße Existenz verwirrend ist, hätte ich dann recht?

„Nun, das hat mir den Tag versüßt, Ellie.“

„Java 7 hat eine neue Anweisung, die die finalize- Methode ersetzt . Sie heißt try-with-resources . Sie ist nicht wirklich ein Ersatz für finalize , sondern ein alternativer Ansatz.“

„Ist es wie Try-Catch, aber mit Ressourcen?“

„Es ist fast wie try-catch . Die Sache ist, dass im Gegensatz zur finalize ()-Methode der final- Block in einer try- catch-finally- Anweisung immer ausgeführt wird. Programmierer haben diese Technik auch verwendet, wenn sie Ressourcen freigeben mussten, Threads schließen usw.

„Hier ist ein Beispiel:“

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

„Unabhängig davon, ob der Try- Block ordnungsgemäß ausgeführt wurde oder eine Ausnahme aufgetreten ist, wird der Final- Block immer aufgerufen und es ist möglich, dort belegte Ressourcen freizugeben.“

„Also wurde in Java 7 die Entscheidung getroffen, diesen Ansatz offiziell zu machen, etwa so:“

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

„Diese spezielle Try- Anweisung heißt try-with-resources (ähnlich wie Sammlungen eine Alternative für foreach haben ).“

„Beachten Sie, dass es nach dem Try Klammern gibt, in denen Variablen deklariert und Objekte erstellt werden. Diese Objekte können innerhalb des Try-Blocks verwendet werden, der durch die geschweiften Klammern angezeigt wird. Wenn der Try-Block mit der Ausführung fertig ist, unabhängig davon, ob er normal oder dort beendet wurde eine Ausnahme war, wird die Methode close() für alle Objekte aufgerufen, die innerhalb der Klammern erstellt wurden.“

„Wie interessant! Diese Notation ist viel kompakter als die vorherige. Ich bin mir nicht sicher, ob ich sie schon verstanden habe.“

„Es ist nicht so schwierig, wie Sie denken.“

„Kann ich also die Klasse jedes Objekts in den Klammern angeben?“

„Ja natürlich, sonst würden die Klammern wenig nützen.“

„Und wenn ich nach dem Verlassen des Try-Blocks eine andere Methode aufrufen muss, wo platziere ich das?“

„Die Dinge sind hier etwas subtiler. Java 7 führt die folgende Schnittstelle ein:“

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

„Ihre Klasse kann diese Schnittstelle implementieren. Und dann können Sie ihre Objekte in einer Try-with-Resources-Anweisung verwenden. Nur solche Objekte können in den Klammern einer Try-with-Resources-Anweisung für den „automatischen Abschluss“ erstellt werden.“

„Mit anderen Worten, ich muss die Close-Methode überschreiben und darin Code schreiben, um mein Objekt zu „bereinigen“, und ich kann keine andere Methode angeben?“

„Ja. Aber Sie können mehrere Objekte angeben – trennen Sie sie einfach durch ein Semikolon:“

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

„Das ist besser, aber nicht so cool, wie ich gehofft hatte.“

„So schlimm ist es nicht. Man wird sich daran gewöhnen. Mit der Zeit.“