JavaRush /Java-Blog /Random-DE /Unterschiede zwischen Konstruktoren und gewöhnlichen Meth...
fog
Level 18

Unterschiede zwischen Konstruktoren und gewöhnlichen Methoden.

Veröffentlicht in der Gruppe Random-DE
Ein Konstruktor ist eine spezielle Methode, die zunächst die Werte der Felder eines Objekts festlegen soll. Auf den ersten Blick unterscheiden sich Objektkonstruktoren nicht wesentlich von gewöhnlichen Objektmethoden. Und tatsächlich können wir innerhalb des Konstruktors alles tun, was wir auch in regulären Objektmethoden tun können: Text an die Konsole ausgeben, auf alle Felder und Methoden des neuen Objekts zugreifen, Ausnahmen auslösen und so weiter. Genau wie reguläre Methoden können Konstruktoren Argumente haben. Genau wie bei überladenen Methoden kann es mehrere Konstruktoren mit unterschiedlichen Signaturen geben. Genau wie generische Methoden können Konstruktoren durch Typvariablen parametrisiert werden. Selbst wenn wir uns den vom Compiler generierten Bytecode ansehen, finden wir an der Stelle, an der der Konstruktor aufgerufen werden sollte, einen Aufruf einer Methode, deren Name sich nicht vom Aufruf anderer Methoden <init>unterscheidet das Objekt. Und nachdem wir den Bytecode dieser Methode gefunden haben, werden wir feststellen, dass er das Ergebnis der Kompilierung unseres Konstruktors enthält. Es scheint, dass es nicht viele Unterschiede zu herkömmlichen Methoden gibt, aber es gibt sie, und zwar durchaus bedeutende. Lassen Sie uns zunächst herausfinden, warum wir eigentlich Konstruktoren benötigen. Um beliebige Daten zu speichern und zu verarbeiten, seien es primitive Typen, Arrays oder Objekte, benötigen wir eine bestimmte Menge an Speicher. Dies können Prozessorregister, Stapelspeicher oder ein im Prozessdatenabschnitt oder in einem dynamisch zugewiesenen Teil des Speichers (Heap) zugewiesener Speicherplatz sein. Wenn in vielen Programmiersprachen ein Programm zur Beschleunigung einen neuen Speicherbereich anfordert, wird der Speicher dem Programm nicht gelöscht und kann beliebige Daten enthalten, die zuvor in dieser Speicherzelle gespeichert wurden. Das Vorbereiten und Schreiben der notwendigen Werte in einen solchen Speicher, damit am Ende dort eine sinnvolle Datenstruktur entsteht, lag vollständig auf den Schultern des Programmierers. Ganz natürlich wollten Programmierer ihr Leben einfacher machen und schrieben Routinen, um häufig verwendete Datenstrukturen zu initialisieren (d. h. Anfangswerte festzulegen). Solche Routinen wurden fast ständig verwendet, daher beschlossen die Entwickler der Java-Sprache, den Aufruf solcher Initialisierungsroutinen beim Erstellen von Objekten obligatorisch zu machen, und nannten sie Konstruktoren . Wenn in Java ein neues Objekt erstellt wird, geschieht Folgendes: Zunächst weist der Java-Speichermanager die für die Aufnahme des Objekts erforderliche Speichermenge zu. Dabei werden nicht nur die direkt in der Klasse des erstellten Objekts deklarierten Felder berücksichtigt, sondern auch die in allen Vorfahren dieser Klasse deklarierten Felder. Darüber hinaus bietet dieses Volumen Platz für die Platzierung von Strukturen, die von der Java-Maschine für interne Zwecke verwendet werden. Alle Felder eines solchen „Leerzeichens“ werden automatisch auf Standardwerte gesetzt – nullfür Referenztypen, 0für Zahlen und falsefürboolean. Danach wird automatisch der Klassenkonstruktor aufgerufen, dessen Aufgabe darin besteht, die Anfangswerte der Felder des Objekts festzulegen. Während bei einer normalen Methode die erste Anweisung alles sein kann, hat der Konstruktor viel weniger Freiheit. Die erste Anweisung eines Konstruktors muss entweder ein expliziter Aufruf eines anderen Konstruktors derselben Klasse oder ein expliziter oder impliziter Aufruf eines Konstruktors einer übergeordneten Klasse sein. Explizite Aufrufe an Konstruktoren derselben Klasse erfolgen über ein Schlüsselwort, thisgefolgt von einer Reihe von Argumenten in Klammern. Der explizite Aufruf des Konstruktors einer übergeordneten Klasse erfolgt auf genau die gleiche Weise, jedoch wird das Schlüsselwort verwendet super. In den Argumenten eines expliziten Aufrufs des Konstruktors derselben oder der übergeordneten Klasse können Sie nicht auf die Felder und Methoden des Objekts zugreifen und auch nicht die Schlüsselwörter und verwenden, da ein expliziter Aufruf des Konstruktors einen statischen Kontext thiseinführt super. Um den Konstruktor einer übergeordneten Klasse implizit aufzurufen, müssen Sie nichts schreiben. Es wird jedoch implizit der Standardkonstruktor aufgerufen, der vorhanden und für die aktuelle Klasse sichtbar sein muss. Gleichzeitig ist zu bedenken, dass das ObjectObjekt, also die Methode, nicht finalisierbar ist, wenn die Kette aufrufender übergeordneter Konstruktoren unterbrochen wird, bevor der an der Spitze der Kette stehende Klassenkonstruktor seine Arbeit erfolgreich abgeschlossen hat finalize()eines solchen Objekts wird niemals aufgerufen. Nachdem der Konstruktor der übergeordneten Klasse abgeschlossen ist, wird die Steuerung implizit an die Instanzinitialisiererblöcke und Instanzfeldinitialisierer der aktuellen Klasse übertragen. Initialisierer werden in der Reihenfolge ausgeführt, in der sie im Programmtext erscheinen. Erst nachdem die Initialisierer ihre Arbeit abgeschlossen haben, wird die Kontrolle an den Rest des Konstruktors übertragen. Die übrigen Funktionen der Konstruktoren beziehen sich auf das Java-Speichermodell. Wenn eine Klasse oder einer ihrer Vorfahren die Methode überschreibt, finalize()erfolgt die Fertigstellung des Konstruktors vor ( passiert vor ) der Ausführung der Methode finalize(). Wenn ein Thread nach Abschluss des Konstruktors einen Verweis auf ein Objekt sah, ist garantiert, dass dieser Thread die korrekt initialisierten finalFelder des Objekts sieht, dessen Initialisierung vor Abschluss des Konstruktors erfolgte.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION