Ich habe kein vollständiges Verständnis für statische Konstruktoren in Java erhalten. Wenn es erlaubt ist, warum ist es erlaubt? In welchen Szenarien würden Sie es verwenden? Welchen Zweck würde es erfüllen? Kann mir bitte jemand ein einfaches Beispiel geben?
11
Antworten:
Streng genommen Java hat keine statischen Konstruktoren , weil ein Konstruktor per definitionem nicht sein statisch. Was Sie meinen, wird als "statischer Initialisierungsblock" bezeichnet. Ein Konstruktor impliziert, dass Sie ein Objekt konstruieren. Sie können keinen Konstruktor für eine Klasse haben, da eine Klasse keine Instanz von sich selbst ist. Es ist einfach eine Klasse. Das, was die Klasse "konstruiert", heißt Compiler (oder virtuelle Maschine, je nachdem, was unter "Konstrukten" zu verstehen ist). Wenn Sie Code innerhalb eines anderen Codes erstellen, beginnen Sie mit der Codegenerierung ein ganz anderes Tier.
Abgesehen von der Nichtauswahl wird ein statischer Initialisierungsblock verwendet, um komplexe statische Felder (oder Felder auf Klassenebene) für eine Klasse zu initialisieren. Normalerweise werden diese verwendet, um Dinge zu initialisieren, die entweder nicht in einer Zeile initialisiert werden können oder die erfordern, dass zuerst ein anderes Objekt (das möglicherweise in der Klasse ist, in der der statische Block implementiert ist oder nicht) initialisiert wird.
Grundsätzlich könnte man sie verwenden, um der Klasse zu sagen: "Hey, setze die Variable A ZUERST auf diesen Wert und verwende dann, sobald dies erledigt ist, den Wert von A, um B zu initialisieren." Da Java erfordert, dass die Standardfeldinitialisierung entweder innerhalb eines Konstruktors oder einer Methode oder über den Aufruf eines Konstruktors oder einer Methode (sofern es sich nicht um ein Literal handelt) erfolgt, können diese eine bequeme Methode zum Initialisieren komplexer statischer Objekte sein.
Statische Initialisierungsblöcke werden nicht allzu oft benötigt und sollten im Allgemeinen vermieden werden, es sei denn, sie haben eine echte Verwendung. Versteh mich nicht falsch, sie haben ihren Platz in Java, aber wie viele andere Dinge (wie break-, return-, switch- und goto-Anweisungen) können sie leicht überbeansprucht werden, was ihre Lesbarkeit und Wartbarkeit des Codes verringert -Basis, in der sie verwendet werden.
Ein kurzes Beispiel für die Verwendung eines statischen Initialisierungsblocks wäre das Folgende (gemäß der hervorragenden Erklärung der hier gefundenen statischen Initialisierungsblöcke ):
Code:
Ausgabe:
Einige Fälle, in denen statische Blöcke nützlich sein können:
Einige Gründe, statische Blöcke NICHT zu verwenden (in anderen Situationen):
this
Schlüsselwort nicht verwenden, da keine Instanz vorhanden ist.Ich sollte beachten: Während einige Sprachen (wie C #) möglicherweise eine Syntax für "Konstruktoren" haben, die statisch sind, funktionieren diese "Konstruktoren" ähnlich wie statische Initialisierungsblöcke in Java und werden von vielen (einschließlich mir) als angesehen Fehlbezeichnungen in der Sprache angesichts des Grundkonzepts eines OOP-Konstruktors .
quelle
Es wird verwendet, um Felder zu initialisieren, die schwieriger sind, als sie einfach zuzuweisen:
Es ist nicht möglich, eine Karte bei der Initialisierung zu füllen (es sei denn, Sie verwenden den anonymen Unterklassen-Hack). Dies ist daher der beste Weg, um sicherzustellen, dass sie vor der ersten Verwendung gefüllt wird
Sie können dies auch tun, um beim Initialisieren aktivierte Ausnahmen abzufangen
quelle
Gurgadurgens Antwort ist wahrscheinlich das, wonach Sie suchen, aber ich füge nur ein paar andere Punkte hinzu, die manchmal vernachlässigt werden, wenn jemand einen "statischen Konstruktor" will.
Wenn Sie eine statische Methode wünschen, die eine Instanz Ihrer Klasse erstellt, können Sie eine statische Methode erstellen, die einfach den Konstruktor der Klasse aufruft.
Dies erzeugt die Ausgabe:
Der andere Grund, eine statische Methode zum Erstellen einer Instanz zu erstellen, ist der Fall, wenn Sie sicherstellen möchten, dass zu einem bestimmten Zeitpunkt genau eine Instanz Ihrer Klasse vorhanden ist. Dies wird als Singleton bezeichnet . Konventionell würde eine solche Klasse eine statische Methode bereitstellen, die aufgerufen wird
getInstance()
, um die einzige Instanz zu erhalten , die als "Singleton" behandelt wird.Dies erzeugt Folgendes.
Wenn Sie einen Verweis auf den Singleton speichern und dann ändern, wird beim nächsten Aufruf
getInstance()
dieser geänderte Singleton abgerufen.Es ist verlockend, Singletons zu verwenden, um globale Variablen für Ihre Anwendung zu erstellen. In einigen Kontexten kann dies nützlich sein, aber es kann Sie auch in Schwierigkeiten bringen. Insbesondere bei der Entwicklung einer Android-App stieß ich auf einen interessanten Fehler, bei dem Singleton-Instanzen verloren gehen konnten. Das Springen von einer Aktivität zu einer anderen kann manchmal dazu führen, dass die JVM einen neuen "Klassenlader" verwendet, der nichts über den Singleton weiß, der von einem vorherigen Klassenlader statisch gespeichert wurde.
quelle
Obwohl ich verstehe, dass es viele gibt, die den Begriff eines "statischen Konstruktors" als Fehlbezeichnung ansehen, glaube ich nicht, dass dies der Fall ist. Das Problem besteht darin, beide Klassen und ihre Instanzobjekte zu erstellen . In anderen Threads wurde angegeben, dass die Konstruktion der Klasse die Aufgabe des Compilers ist. Selbst in Java ist dies nur zur Hälfte der Fall.
Der Compiler erstellt für jede Klassendefinition ein Gerüst. Das Gerüst enthält Metadaten über die Klasse und welche Instanzen zum Zeitpunkt der Erstellung enthalten sein sollten. Wenn eine Klasse ein Feld definiert, dem ein konstanter Grundwert zugewiesen ist, wird dieser Wert vom Compiler in das Gerüst aufgenommen. Für alle anderen zugewiesenen Werttypen generiert der Compiler eine Initialisierungsroutine, die vor der Erstellung der Instanz der ersten Klasse einmal ausgeführt werden soll und das Gerüst mit den richtigen Werten aktualisiert. Dieses Update kann vom Compiler nicht durchgeführt werden.
Da diese einmalige Aktualisierung des Gerüsts häufig eine wichtige Voraussetzung für das ordnungsgemäße Funktionieren der Instanzkonstruktoren ist, ist es auch sinnvoll, sie als Konstruktortyp zu bezeichnen. Aus diesem Grund wird es in gängigen OO-Sprachen, die das Konzept unterstützen, als statischer Konstruktor bezeichnet. Das Konzept hinter den statischen Initialisierungsblöcken in Java ist kaum mehr als eine semantische Änderung, um der Vorstellung zu entsprechen, dass ein Java-Programmierer sowohl system- als auch implementierungsunabhängig sein sollte.
quelle
Wie andere Antworten bereits sagten, können Sie statische Methoden schreiben, die ein Objekt erstellen. Dies umgeht das Fehlen benannter Konstruktoren in Java (und vielen anderen Sprachen. Delphi unterstützt benannte Konstruktoren). Sie können mit den Typen und der Reihenfolge der Parameter spielen, dies kann jedoch zu unklarem und fragilem Code führen.
Zum Beispiel könnten wir ein Szenario erfinden, in dem Ihr Objekt aus einer XML-Zeichenfolge oder einer JSON-Zeichenfolge erstellt werden kann. Sie könnten Methoden schreiben wie:
Ich habe dies sehr gelegentlich als Alternative zu einem parameterlosen Konstruktor mit benannten Initialisierungsmethoden verwendet:
Sie können eine statische Erstellungsmethode als Implementierung des Builder-Musters in Ihrer Klasse betrachten.
quelle
Sie können den Abschnitt "statisch" wie einen Konstruktor auf Klassenebene anzeigen, mit dem Klasseneigenschaften initialisiert werden (statisch in Java). Das gleiche wie der "normale" Konstruktor, der zum Initialisieren von Eigenschaften auf Instanzebene verwendet wird.
quelle