2009-08-31 9 views
61

Mit anderen Worten, warum benötigen Sie einen Instanzinitialisierer? Welchen Unterschied oder welchen Vorteil haben Sie beim Schreiben eines Instanzinitialisierers über einen Konstruktor?Wie unterscheidet sich ein Instanzinitialisierer von einem Konstruktor?

+1

Instanzinitialisierer sind ziemlich selten (es sei denn, Sie stoßen auf Code von jemandem, der an der doppelten Klammersprache interessiert ist). –

Antwort

88

Dies scheint es gut zu erklären:

Instanz initializers eine sinnvolle Alternative zu Instanzvariable initializers wann immer:

  • initializer Code Ausnahmen abfangen müssen, oder

  • ausführen Fantastische Berechnungen, die nicht mit einem Instanzvariableninitialisierer ausgedrückt werden können. Sie könnten natürlich immer einen solchen Code in Konstruktoren schreiben.

Aber in einer Klasse, die mehrere Konstrukteure hätten, würden Sie den Code in jedem Konstruktor wiederholen. Mit einem Instanzinitialisierer können Sie den Code nur einmal schreiben, und es wird ausgeführt, egal was Konstruktor zum Erstellen des Objekts verwendet wird. Instanzinitialisierer sind auch nützlich in anonymen inneren Klassen, die keine Konstruktoren überhaupt deklarieren können.

Von: JavaWorld Object initialization in Java.

+14

Auf der anderen Seite können Sie Code einmal in einem Konstruktor schreiben und nur von allen anderen Konstruktoren aufrufen. Aber anonyme innere Klassen machen einen guten Punkt. –

+10

Sie können es von anderen Konstruktoren aufrufen - aber Sie wiederholen den Anruf erneut. Wenn Sie einen neuen Konstruktor hinzufügen, müssen Sie daran denken, den Aufruf hinzuzufügen. Nicht so bei einem Instanzinitialisierer. – talonx

+5

@talonx, ich stimme deinem Argument über das Vergessen zu, aber die Verwendung von Standardverhalten ist gleichermaßen gefährlich. Wenn ein Supporter einen Konstruktor im Legacy-Code liest, würde man nicht immer daran denken, nach möglichen Instanz-Initialisierern zu suchen. Dagegen wird ein explizit verwendetes init() hervorstechen. – Assambar

7

Wenn Sie viele Konstruktoren haben und möchten, dass ein gemeinsamer Code für jeden Konstruktor ausgeführt wird, können Sie den Instanzinitialisierer verwenden. Er wird für alle Konstruktoren aufgerufen.

18

In Bezug auf den Objektlebenszyklus gibt es keinen Unterschied. Beide werden zur Konstruktionszeit aufgerufen, und logisch kann der Initialisierungsblock als Teil der Konstruktion betrachtet werden.

Semantisch ist ein initializer ein nettes Tool für mehrere Gründe zu haben:

der Initialisierer kann, indem die Initialisierung Logik neben der Variablen initialisiert wird die Lesbarkeit des Codes verbessern:

public class Universe { 
     public int theAnswer; 
     { 
     int SIX = 6; 
     int NINE = 7; 
     theAnswer = SIX * NINE; 
     } 

     // a bunch of other vars 
    } 

vs

public class Universe { 
     public int theAnswer; 

     // a bunch of other vars 

     public Universe() { 
     int SIX = 6; 
     int NINE = 7; 
     theAnswer = SIX * NINE; 

     // other constructor logic 
     } 
    } 

Initialisierer werden unabhängig von aufgerufen, von denen Konstruktor verwendet wird.

Initialisierer können in anonymen inneren Klassen verwendet werden, wo Konstruktoren nicht können.

+3

Was Sie haben, ist ihr technisch ein "Instanzvariableninitialisierer" und kein "Instanzinitialisierer" (ein Block, der direkt in einer Klasse verschachtelt ist). Siehe JLS 3. Abschnitt 8.6. –

+0

Oh, alles klar. Das Beispiel wurde geändert. – ykaganovich

+0

Instanzinitialisierungsblock hat keinen Namen wie hier gezeigt (http://www.javatpoint.com/instance-initializer-block). Ist es nicht? Sie haben Ihren Instanzinitialisierungscode mit dem Namen "theAnswer" markiert. Ist das korrekt? oder ich vermisse etwas. – RBT

4

Ich würde das Instanzinitialisierungs-Idiom im Allgemeinen vermeiden - der einzige wirkliche Vorteil, den es über Variableninitialisierungen gibt, ist die Ausnahmebehandlung.

Und da eine init-Methode (aufrufbar vom Konstruktor) auch die Exception-Behandlung ausführen kann und auch Konstruktor-Setup-Code zentralisiert, aber den Vorteil hat, dass sie mit Konstruktor-Parameterwerten arbeiten kann, würde ich sagen, dass der Instanz-Initialisierer redundant ist. und deshalb zu vermeiden.

+1

Sie müssten die INIT-Methode in ALLEN Konstruktoren manuell aufrufen. – Stephan

+2

@Alex Guter Punkt, aber da die meisten Klassen mit mehreren Konstruktoren eine gemeinsame Logik haben, neigen sie dazu, sich trotzdem gegenseitig anzurufen. Zumindest in den meisten meiner Klassen. – CPerkins

0

Initialisierer ist eine Möglichkeit, Code zwischen Konstruktoren zu teilen und Code lesbarer zu machen, wenn Initializer mit Variablendeklaration verwendet wird.

Der Java-Compiler kopiert Initialisierungsblöcke in jeden Konstruktor. Daher kann dieser Ansatz verwendet werden, um einen Codeblock zwischen mehreren Konstruktoren zu teilen. Oracle documentation

4

Der wirkliche Vorteil Instanz initializers über Konstrukteure sehen ist, wenn wir eine anonyme innere Klasse verwenden.

Anonyme innere Klassen können nicht einen Konstruktor haben (wie sie anonym sind) ,so sie eine ziemlich natürliche Ergänzung für Instanz initializers sind.

Verwandte Themen