Impressum · Kontakt · Hilfe
Besucher online · Mitglieder



Portal > Foren > Java > Allgemeine Java-Programmierung > Warum gibt es Destruktoren in Java?
Antwort
 
Themen-Optionen
Alt 13.02.2005, 23:57   Nach oben    #1
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard Warum gibt es Destruktoren in Java?

Hallo,
okay .. stelle ich hier mal meine erste Fachfrage bzgl. Java.

Es geht um etwas, was ich soeben gefunden habe ... Destruktoren in Java.
Guido Krüger schreibt.
Zitat:
Neben Konstruktoren, die während der Initialisierung eines Objekts aufgerufen werden, gibt es in Java auch Destruktoren. Sie werden unmittelbar vor dem Zerstören eines Objekts aufgerufen.

Ein Destruktor wird als geschützte (protected) parameterlose Methode mit dem Namen finalize definiert:
Java Code:
  1. protected void finalize()
  2. {
  3.    ...
  4. }
Da Java über ein automatisches Speichermanagement verfügt, kommt den Destruktoren hier eine viel geringere Bedeutung zu als in anderen objektorientierten Sprachen. Anders als etwa in C++ muß sich der Entwickler ja nicht um die Rückgabe von belegtem Speicher kümmern; und das ist sicher eine der Hauptaufgaben von Destruktoren in C++.

Tatsächlich garantiert die Sprachspezifikation nicht, daß ein Destruktor überhaupt aufgerufen wird. Wenn er aber aufgerufen wird, so erfolgt dies nicht, wenn die Lebensdauer des Objektes endet, sondern dann, wenn der Garbage Collector den für das Objekt reservierten Speicherplatz zurückgibt. Dies kann unter Umständen nicht nur viel später der Fall sein (der Garbage Collector läuft ja als asynchroner Hintergrundprozeß), sondern auch gar nicht. Wird nämlich das Programm beendet, bevor der Garbage Collector das nächste Mal aufgerufen wird, werden auch keine Destruktoren aufgerufen. Selbst wenn Destruktoren aufgerufen werden, ist die Reihenfolge oder der Zeitpunkt ihres Aufrufs undefiniert. Der Einsatz von Destruktoren in Java sollte also mit der nötigen Vorsicht erfolgen.
Quelle: Handbuch der Java Programmierung / www.javabuch.de

Jou. Also da steht kurz, dass man gar nicht sicherstellen kann, dass der Destruktor überhaupt aufgerufen wird.
Darf ich mal ganz kurz fragen, warum es dann überhaupt so etwas wie einen Destruktor gibt?

Da steige ich nämlich nicht wirklich hinter.

Danke Euch.

Grüße Ben.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:07   Nach oben    #2
Benutzer
 
Benutzerbild von mr1st
 
Registriert seit: 08.02.2005
Ort: Wien
Beiträge: 85
Standard

Grob gesagt könnte man sagen, dass Sun die völlig umsonst reingetan hat.
In anderen Programmiersprachen ist es üblich, in den Desruktoren die Ressourcen freizugeben, in Java werden dafür aber meist eigene Methoden verwendet, da die Destruktoren von Java nicht brauchbar dafür sind (zB die close() Methoden bei Streams).
Vielleicht hat Sun die nur reingegeben, weil ja die meisten anderen Programmiersprachen auch welche haben. Effektiv haben sie aber, wie gesagt, gar keinen Wert.

Am besten gar nicht verwenden, einfach deren Existenz ingorieren.

MfG
__________________
Kosmetik Hobby
mr1st ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:17   Nach oben    #3
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Zitat:
Am besten gar nicht verwenden, einfach deren Existenz ingorieren.
Hm. Ich habe befürchtet, dass so etwas kommt
Ist ja irgendwie nicht befriedigend, oder?

Es ist so viel Zeug als "deprecated" markiert, warum werden dann die Destruktoren nicht auch einfach entfernt?

Hm. Alles unverständlich ... finde ich ..
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:20   Nach oben    #4
mic_checker
Gast
 
Beiträge: n/a
Standard

Also zum einen: Was sicher schon klar geworden ist: In Java spielen Destruktoren bei weitem nicht so eine wichtige Rolle wie z.B in C++. Dies liegt an dem GC (Garbage Collector).
Willst du nun das vor der tatsächlichen "Zerstörung" eines Objekts best. Operationen noch ausgeführt werden, so kannst du eine finalize() Methode implementieren und in dieser entsp. Schritte durchführen.

Allerdings steht im Handbuch ja auch das es nicht sichergestellt ist das der Compiler tatsächlich finalize() aufruft.

Ich denke Destruktoren sind in einigen wenigen Bereichen vielleicht ganz sinnvoll, aber im normalen Gebrauch nicht. Ist zumindest meine Meinung.

Wenn du eine Referenz auf ein Objekt hast, dann weiss diesem lieber "null" zu um es zu "löschen", da Objekte automatisch gelöscht werden wenn keine Referenz mehr darauf existiert.
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:24   Nach oben    #5
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Ich habe schon verstanden, was da steht. Ist ja nicht wirklich anspruchsvoll
Mir ging es mehr um den Sinngehalt der Destruktoren, der aber ja anscheinend nicht wirklich vorhanden ist.

Grüße Ben.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:27   Nach oben    #6
mic_checker
Gast
 
Beiträge: n/a
Standard

Ich habe nicht bezweifelt das du das verstanden hast, nur vielleicht liest sich jemand das hier durch der noch nichts davon gehört hat .

Wie gesagt, abgesehen davon das du vielleicht in finalize() best. Operationen durchführen willst (da deine Objekte Netzwerkverbindungen geöffnet haben etc.), kannst du dort z.B. diese schließen oder andere schöne Dinge anstellen.

Mich hat diese Antwort auch nicht befriedigt , aber unser Prof konnte auch nicht erkären warum die Leute von SUN es nun (so) implementiert haben.
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:38   Nach oben    #7
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Zitat:
Wie gesagt, abgesehen davon das du vielleicht in finalize() best. Operationen durchführen willst (da deine Objekte Netzwerkverbindungen geöffnet haben etc.), kannst du dort z.B. diese schließen oder andere schöne Dinge anstellen.
An das Schließen von solchen Verbindung hatte ich auch erst gedacht, allerdings ist es meiner Ansicht nach sicherlich sinnvoller, wenn diese Verbidnung explizit gekappt werden. Denn wie ja oben steht kann man gar nicht sicherstellen, dass die Destruktoren überhaupt laufen.

Man könnte maximal in Destruktoren überprüfen, ob nicht doch noch irgendwas aufgrund irgendwelcher fehlerhafter Operationen im Programm zu "schließen" etc. ist und dann Anweisungen ausführen, die eben dies tun.

Das wäre dann z.B. noch eine Absicherung, die zwar nicht immer verfügbar ist, aber eventuell das Ausmaß von Fehlern reduzieren kann.

Was anderes fällt mir beim besten Willen nicht ein.

Grüße Ben.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:44   Nach oben    #8
mic_checker
Gast
 
Beiträge: n/a
Standard

Zitat:
An das Schließen von solchen Verbindung hatte ich auch erst gedacht, allerdings ist es meiner Ansicht nach sicherlich sinnvoller, wenn diese Verbidnung explizit gekappt werden. Denn wie ja oben steht kann man gar nicht sicherstellen, dass die Destruktoren überhaupt laufen.
Da stimm ich dir zu, es ist sicher besser so schon zu probieren die Verbindungen explizit zu trennen. Vielleicht kann einer von den zuständigen Programmierern von SUN hier mal gerad ne Stellungnahme posten ? *g*

Wäre auch froh wenn jemand mal hieb und stichfeste argumente liefern könnte.
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 11:57   Nach oben    #9
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Zitat:
Vielleicht kann einer von den zuständigen Programmierern von SUN hier mal gerad ne Stellungnahme posten ? *g*
Ähm. Nee. *gg* In diesem Leben wohl nicht mehr.

Gut. Ich habe mal etwas in den Foren auf SUN rumgestöbert. Und da steht genau das selbe, was wir hier auch von uns gegeben haben.

Selbst der Aufruf von System.gc(); reicht nicht aus um abzusichern, dass der GarbageCollector anfängt u.a. Destruktoren aufzurufen.

Nunja. Da muss ich mich wohl mit dieser unbefriedigenden Antwort begnügen.

Danke und Grüße Ben.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 20:46   Nach oben    #10
Fuzzy
Gast
 
Beiträge: n/a
Standard

Hi Ben,

wie Du vorhin schon (in einem Nebensatz)festgestellt hast:

Man braucht den finalize praktisch nur zum Aufräumen von Ressourcen, wenn jemand vergessen hat, close() aufzurufen. Im Client-Betrieb kann vielleicht darauf verzichten, aber bei Server-Betrieb passiert eine Garbage-Collection schon mal öfter... Und im Server-Betrieb ist so eine Selbstheilung echtes Gold wert.

Ach übrigens: Wenn man eine gc() braucht: Mehrfach aufrufen und zwischendurch warten reicht meist aus...
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 20:53   Nach oben    #11
Fuzzy
Gast
 
Beiträge: n/a
Standard

... und Du hast vergessen, dass man in einem finalizer UNBEDINGT super.finalize aufrufen MUSS.

Java Code:
  1. protected void finalize() {
  2.   try {
  3.      // ... hier den eigenen Code eingeben
  4.   } finally {
  5.      super.finalize();
  6.   }
  7. }

Viel Erfolg beim eigenen finalizer...
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 21:55   Nach oben    #12
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Zitat:
... und Du hast vergessen, dass man in einem finalizer UNBEDINGT super.finalize aufrufen MUSS.

Java Code:
  1. protected void finalize() {
  2.   try {
  3.      // ... hier den eigenen Code eingeben
  4.   } finally {
  5.      super.finalize();
  6.   }
  7. }

Viel Erfolg beim eigenen finalizer...
Warum muss man das?
Ich dachte, dass die finalize()-Methode aus Objekt leer implementiert .. .. hab ich da eine falsche Information?

Danke ..
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 22:14   Nach oben    #13
Fuzzy
Gast
 
Beiträge: n/a
Standard

... solange Du Dich von Object ableitest stimmt das.

Aber Du leitest Dich nicht unbedingt von Object ab und wenn Du das nicht tust und in Deinem Code eine Exception geworfen wird, werden die "Parent"-Klassen nicht finalisiert.

Und den Fehler such dann mal schön...
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 14.02.2005, 22:21   Nach oben    #14
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Okay. Ist verständlich, da ich ja normalerweise auch nicht von Object ableite.
Jo, okay. Da werde ich meinen FAQ-Beitrag nochmals überarbeiten.

Danke.
Grüße Ben.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 10:02   Nach oben    #15
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Okay.
Ich hoffe, dass das richtig und einigermaßen verständlich zusammenfasst wurde.
http://www.php-info.org/ftopic96.html

Grüße Ben ;_)

Geändert von Jann Hendrik (05.06.2007 um 09:10 Uhr). Grund: php-info.org - link entfernt.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 10:07   Nach oben    #16
Fuzzy
Gast
 
Beiträge: n/a
Standard

... normalerweise schreibt man im Finalizer Code z.B. wie folgt:
Java Code:
  1. protected void finalize() {
  2.   try {
  3.      if (!closed)
  4.        close();
  5.   } finally {
  6.      super.finalize();
  7.   }
  8. }

Dadurch wird beim Aufräumen die close() Methode aufgerufen, wenn das nicht schon ohnehin passiert ist.
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 10:08   Nach oben    #17
Sym
Chefkoch-Mod
 
Benutzerbild von Sym
 
Registriert seit: 30.05.2004
Beiträge: 433
Standard

Ganz ehrlich?

Der Text klingt ein wenig wischi-waschi. So als würder der GC selber handeln - nach dem Zufallsprinzip. Dem ist aber ja nun nicht so. Er kommt, wenn der Rechner genug Kapazitäten dafür frei hat. Notfalls müsste man das Programm anhalten, damit der GC aufräumen kann.

Und die Stelle "GC mehrmals aufrufen und dazwischen warten" klingt auch sehr komisch. Gut, er ist dann öfter in der Schleife und hat somit eine höhere Wahrscheinlichkeit dran zu kommen, aber ob das der richtige Weg ist?

Sonst ist es aber ok.
__________________
Denk mal darüber nach...

Lars

ACHTUNG: wenn ich von Klassen spreche, könnte ich auch deren Instanzen meinen.
www.linuxforen.de +++ www.macuser.de +++ www.mrunix.de +++ www.lmprojects.de
Sym ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 10:09   Nach oben    #18
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

Wo wird denn die Variable "closed" definiert?
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 10:15   Nach oben    #19
Fuzzy
Gast
 
Beiträge: n/a
Standard

@Ben: Das war ein Beispiel. Wenn man close() mehrfach schadlos hinterienander aufrufen kann, kann man auch einfach nur close() angeben.

@sym: Die Tücke ist, dass zum einen genügend Kapazität frei sein muß, damit mit System.gc() der Garbage Collector überhaupt losläuft und zum anderen es nicht zwingend gesagt ist, das in einem Lauf alle Objekte behandelt werden. Deshalb muß man - um sicherzugehen - den gc mehrfach aufrufen mit Pausen dazwischen (wegen der Kapazität). Und wann der GC ansonsten aufgerufen wird, ist natürlich determiniert, aber von GC zu GC und von JVM zu JVM unterschiedlich.
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 10:19   Nach oben    #